Отступ #определяет


Я знаю, что #defines и др. обычно никогда не отступает. Зачем?

Я работаю в каком-то коде в данный момент, который имеет ужасную смесь #defines,#ifdef s,#else s,#endif s, etc. Все это часто смешивается с обычным кодом C. Отсутствие отступов #defines делает их трудно читать. И смесь с отступом код с отступом #defineS-это кошмар.

какая польза от отсутствия отступов #defines? Делает ли это меня плохим человеком, если я вмять их? Разве это не намного лучше?

#ifdef SDCC
    #if DEBUGGING == 1
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x3DC0
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x7DC0
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #else
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x4000
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x8000
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #endif
#else
    #if DEBUGGING == 1
        #define FLASH_MEMORY_END 0x7DC0
    #else
        #define FLASH_MEMORY_END 0x8000
    #endif
#endif
7 86

7 ответов:

препроцессор Pre-ANSI C не допускал пространства между началом строки и символом"#"; ведущий " # " всегда должен был помещаться в первый столбец.

компиляторы Pre-ANSI C в наши дни не существуют. Используйте любой стиль (пробел перед " # "или пробел между" # " и идентификатором), который вы предпочитаете.

http://www.delorie.com/gnu/docs/gcc/cpp_48.html

#ifdef SDCC
#  if DEBUGGING == 1
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x3DC0
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x7DC0
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  else
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x4000
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x8000
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  endif
#else
#  if DEBUGGING == 1
#    define FLASH_MEMORY_END 0x7DC0
#  else
#    define FLASH_MEMORY_END 0x8000
#  endif
#endif

Я часто видел этот стиль в старых заголовках Unix, но я ненавижу его, поскольку синтаксическая раскраска часто терпит неудачу в таком коде. Я использую очень видимый цвет для директивы pre-processor, чтобы они выделялись (они находятся на метауровне, поэтому не должны быть частью нормального потока из кодекса). Вы даже можете видеть, что так не красит последовательность полезным образом.

Что касается разбора директив препроцессора, стандарт C99 (и стандарт C89 до него) были ясны о последовательности операций, выполняемых логически компилятором. В частности, я считаю, что это означает, что этот код:

/* */ # /* */ include /* */ <stdio.h> /* */

эквивалентно:

#include <stdio.h>

к лучшему или худшему, GCC 3.4.4 с '-std=C89-pedantic' принимает строку с комментариями, во всяком случае. Я не защищаю это как стиль - ни на секунду (это ужасно). Я просто думаю, что это возможно.

ISO / IEC 9899: 1999 раздел 5.1.1.2 фазы перевода гласит:

  1. [отображение символов, включая триграфы]

  2. [линия сращивания-удаление обратной косой черты новой строки]

  3. исходный файл разбивается на токены предварительной обработки и последовательности пробелы (включая комментарии). Исходный файл не должен заканчиваться частичная предварительная обработка маркера или в частичный комментарий. Каждый комментарий заменяется на один символ пробела. Символы новой строки сохраняются. Является ли каждое непустое последовательность символов пробела, отличных от new-line, сохраняется или заменяется на один символ пробела определяется реализацией.

  4. выполняются директивы предварительной обработки, расширяются вызовы макросов, [...]

раздел 6.10 директивы предварительной обработки гласит:

A директива предварительной обработки состоит из последовательности токенов предварительной обработки, которая начинается с токен # preprocessing, который (в начале фазы перевода 4) является либо первым символом в исходном файле (необязательно после пробела, не содержащего символов новой строки) или что следует за пробелом, содержащим по крайней мере один символ новой строки, и заканчивается следующим символ новой строки.

единственный возможный спор-это скобочное выражение '(в начале фаза перевода 4)', что может означать, что комментарии перед хэшем должны отсутствовать, поскольку они не заменяются пробелами до конца фазы 4.

как отмечали другие, препроцессоры pre-standard C не вели себя единообразно несколькими способами, а пробелы до и в директивах препроцессора были одной из областей, где разные компиляторы делали разные вещи, в том числе не распознавали директивы препроцессора с пробелами перед ними.

Это примечательно, что удаление обратной косой черты-новой строки происходит до анализа комментариев. Следовательно, вы не должны заканчивать // комментарии с обратной косой черты.

Я не знаю, почему это не более распространенная. Конечно, бывают случаи, когда мне нравится отступать от директив препроцессора.

одна вещь, которая продолжает мешать мне (и иногда убеждает меня прекратить попытки), заключается в том, что многие или большинство редакторов/IDE будут бросать директиву в столбец 1 при малейшей провокации. Что чертовски раздражает.

в эти дни я считаю, что это в основном выбор стиля. Я думаю в какой-то момент в далеком прошлом не все компиляторы поддерживали понятие отступа препроцессора defines. Я провел некоторое исследование и не смог подтвердить это утверждение. Но в любом случае, представляется, что все современные компиляторы поддерживают идею выделить препроцессора макрос. У меня нет копии стандарта C или C++, хотя я не знаю, является ли это стандартным поведением или нет.

Как ли это хорошим стилем. Лично мне нравится идея держать их в левой. Это дает вам последовательное место, чтобы искать их. Да, это может раздражать, когда есть очень вложенные макросы. Но если вы отступите от них, вы в конечном итоге получите еще более странный код.

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif

для примера, который вы дали, может быть целесообразно использовать отступ, чтобы сделать его более ясным, поскольку у вас есть такая сложная структура вложенных директив.

лично я думаю, что полезно держать их без отступов большую часть времени, потому что эти директивы работают отдельно от остальной части вашего кода. Директивы, такие как #ifdef, обрабатываются препроцессором до того, как компилятор увидит ваш код, поэтому блок кода после директивы #ifdef может даже не быть compiled.

сохранение директив визуально отделенными от остальной части кода является более важным, когда они перемежаются с кодом (а не выделенный блок директив, как в приведенном примере).

Я работаю на некоторые код на данный момент, который имеет ужасную смесь директивы #define, #ifdefs, #другое, #endifs, #и т. д. Все это часто смешивается с обычным кодом C. Отсутствие отступов #defines затрудняет их чтение. И смесь кода с отступом с не отступом #defines-это кошмар.

общее решение комментировать директивы, так что вы легко знаете, что они относятся к:

#ifdef FOO
/* a lot of code */
#endif /* FOO */

#ifndef FOO
/* a lot of code */
#endif /* not FOO */