缩进#defines

我知道#define s等通常不会缩进。 为什么?

目前我正在编写一些代码,其中有#ifdef#else #ifdef#else#else #endif等等的混合。所有这些经常混入正常的C代码中。 #define的非缩进使得它们很难阅读。 缩进代码与非缩进#define s的混合是一场噩梦。

不缩进#define s有什么好处? 如果我缩进,会不会让我变成坏人? 这不是更好吗?

 #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 

ANSI C之前的预处理程序不允许在行的开头和“#”字符之间留有空格; 领先的“#”必须始终放在第一列。

之前的ANSI C编译器是不存在的。 使用你喜欢的风格(“#”之前的空格或“#”和标识符之间的空格)。

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

正如一些人已经说过的那样,一些Pre-ANSI编译器要求#是在线上的第一个字符,但是他们并不要求de预处理指令被附加到它上面,所以这样做了缩进。

 #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头文件中看到这种风格,但是我讨厌它,因为在这样的代码中语法着色经常失败。 我对预处理器指令使用了非常明显的颜色,以便它们脱颖而出(它们处于元级别,所以不应该成为正常代码stream的一部分)。 你甚至可以看到,SO不会以有用的方式给序列着色。

关于预处理器指令的parsing,C99标准(以及之前的C89标准)明确了编译器在逻辑上执行的操作顺序。 特别是,我相信这意味着这个代码:

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

相当于:

 #include <stdio.h> 

无论如何,无论如何,带有'-std = c89 -pedantic'的GCC 3.4.4都会接受这个注释符号。 我不是主张这是一种风格 – 不是一秒钟(这是可怕的)。 我只是认为这是可能的。

ISO / IEC 9899:1999第5.1.1.2节翻译阶段说:

  1. [字符映射,包括三字母]

  2. [行拼接 – 去除反斜线换行符]

  3. 源文件被分解为预处理令牌和空白字符序列(包括注释)。 源文件不应以部分预处理标记或部分注释结束。 每个评论被replace为一个空格字符。 换行符保留。 是否保留每个非空白字符序列(除了换行符以外)或是否由一个空格字符replace是实现定义的。

  4. 预处理指令被执行,macros调用被扩展,

6.10节预处理指令说:

预处理指令由一系列预处理标记组成,该标记开始于(在翻译阶段4的开始处)源文件中的第一个字符(可选地,在不包含换行符的空白之后)的#预处理标记或者在包含至less一个换行符的空格之后,以下一个换行符结束。

唯一可能的争议是“(在翻译阶段4开始时)”的括号expression式,这可能意味着散列前的注释必须不存在,因为直到第4阶段结束它们才被空格替代。

正如其他人所指出的那样,预标准的C预处理器在许多方面的行为并不一致,在预处理器指令之前和之后的空格是不同编译器做了不同事情的领域之一,包括不识别带有空格的预处理器指令。

值得注意的是,在分析注释之前发生了反斜线 – 换行符的移除。 因此,你不应该用反斜杠结束注释。

这些天我相信这主要是一种风格的select。 在过去的一段时间里,我认为并不是所有的编译器都支持缩进预处理器的定义。 我做了一些研究,无法支持这个说法。 但无论如何,似乎所有现代编译器都支持缩进预处理器macros的想法。 我没有C或C ++标准的副本,所以我不知道这是否是标准行为。

至于是否风格好。 就我个人而言,我喜欢把它们全部留在左边。 它给你一个寻找他们的地方。 是的,当有非常嵌套的macros时它会变得烦人。 但是,如果你缩进它们,你最终会看到更怪的代码。

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

对于你所给的例子来说,使用缩进可以使它更加清晰,因为你有这样一个复杂的嵌套指令结构。

就我个人而言,我认为大部分时间不要缩进是很有用的,因为这些指令与其他代码分开运行。 在编译器看到你的代码之前,像#ifdef这样的指令是由预处理器处理的,所以在#ifdef指令之后的代码块甚至可能不被编译

如果指令与代码的其余部分在视觉上分离,那么当它们穿插代码(而不是指定的专用块,如您所提供的示例)时,则更为重要。

我不知道为什么它不常见。 当然,我喜欢缩进预处理指令。

有一件事阻碍了我(并且有时使我停止尝试),因为许多或大多数编辑/ IDE将会毫不犹豫地将这个指令扔到第一列。 这是讨厌的地狱。

目前我正在编写一些代码,其中有#define,#ifdefs,#elses,#endifs,#etc的混合。 所有这些经常与正常的C代码混合在一起。 #define的非缩进使得它们很难阅读。 缩进代码与非缩进的#defines的混合是一场噩梦。

一个常见的解决scheme是评论指令,以便您轻松知道他们指的是什么:

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