c - 缩进#defines

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

我现在在一些代码中工作,其中包含#defines,#ifdefs,#defines,#endifs等的可怕混合物。所有这些通常与普通的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个解决方案
96 votes

预ANSI-C预处理器不允许在行的开头和"#"之间留出空间。 字符; 领先"#" 必须始终放在第一列。

目前,ANSI-C前编译器不存在。 使用哪种风格(#34之前的空格;#"或#34;#"和标识符之间的空格)。

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

answered 2019-08-11T03:55:35Z
24 votes

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

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

Patrick Schlüter answered 2019-08-11T03:56:09Z
16 votes

关于预处理程序指令的解析,C99标准(以及之前的C89标准)清楚地了解了编译器逻辑执行的操作顺序。 特别是,我相信这意味着这段代码:

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

相当于:

#include <stdio.h>

无论好坏,GCC 3.4.4与&#39; -std = c89 -pedantic&#39; 无论如何,接受评论载货行。 我不是主张这种风格 - 不是一秒钟(它是可怕的)。 我只是认为这是可能的。

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

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

  2. [线拼接 - 删除反斜线换行符]

  3. 源文件被分解为预处理令牌和序列   空格字符(包括注释)。 源文件不得以a结尾   部分预处理令牌或部分注释。 每条评论都被替换为   一个空格字符。 保留换行符。 是否每个都是空的   新行以外的空白字符序列被保留或替换为   一个空格字符是实现定义的。

  4. 执行预处理指令,扩展宏调用,[...]

第6.10节预处理指令说:

预处理指令由一系列以...开头的预处理标记组成   #预处理令牌(在翻译阶段4的开始)是第一个字符   在源文件中(可选地在包含没有换行符的空格之后)或那个   跟随包含至少一个换行符的空格,并由下一个结束   换行符。

唯一可能的争议是括号表达式(在翻译阶段4的开始)&#39;,这可能意味着哈希之前的注释必须不存在,因为它们不会被空格替换直到结束 第4阶段。

正如其他人所指出的那样,预标准C预处理器在多种方式下表现不均匀,并且预处理器指令之前和之中的空格是不同编译器执行不同操作的区域之一,包括不识别前面有空格的预处理器指令。

值得注意的是,在分析注释之前会发生反斜杠换行。因此,您不应以反斜杠结束//注释。

Jonathan Leffler answered 2019-08-11T03:57:59Z
6 votes

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

阻碍我前进的一件事(有时候说服我停止尝试)是许多或大多数编辑/ IDE会在最轻微的挑衅下将指令抛到第1列。 哪个是令人讨厌的地狱。

Michael Burr answered 2019-08-11T03:58:33Z
5 votes

这些天我相信这主要是风格的选择。 我想在遥远的过去的某个时刻,并非所有编译器都支持缩进预处理器定义的概念。 我做了一些研究,无法支持这个断言。 但无论如何,似乎所有现代编译器都支持缩进预处理器宏的想法。 我没有C或C ++标准的副本,所以我不知道这是否是标准行为。

至于它的风格是否合适。 就个人而言,我喜欢将它们全部保留在左侧的想法。 它为您提供了一个一致的位置来寻找它们。 是的,当有非常嵌套的宏时,它会变得烦人。 但如果你缩进它们,你最终会得到更奇怪的代码。

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif
JaredPar answered 2019-08-11T03:59:09Z
3 votes

对于您已经给出的示例,使用缩进来使其更清晰可能是合适的,因为您有这样一个复杂的嵌套指令结构。

我个人认为在大多数情况下保持缩进是很有用的,因为这些指令与其余代码分开运行。 #ifdef等指令在编译器看到代码之前由预处理器处理,因此#ifdef指令之后的代码块甚至可能无法编译。

当指令与代码的其余部分在视觉上分开时更为重要,因为它们散布在代码中(而不是专用的指令块,如您给出的示例中所示)。

Daniel Fortunov answered 2019-08-11T03:59:50Z
2 votes

我现在在一些代码中工作,这些代码混合了#define,#ifdefs,#else,#endifs,#etc。 所有这些通常与普通的C代码混合在一起。 #defines的非缩进使它们难以阅读。 缩进代码与非缩进#defines的混合是一场噩梦。

一个常见的解决方案是对指令进行注释,以便您轻松了解它们所指的内容:

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

#ifndef FOO
/* a lot of code */
#endif /* not FOO */
Bastien Léonard answered 2019-08-11T04:00:23Z
translate from https://stackoverflow.com:/questions/789073/indenting-defines