缩进#defines

Roc*_*net 95 c coding-style code-formatting indentation c-preprocessor

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

我正在使用一些代码,其中包含#defines,#ifdefs,#elses,#endifs等的可怕混合.所有这些通常与正常的C代码混合在一起.#defines 的非缩进使它们难以阅读.缩进代码与非缩进#defines的混合是一场噩梦.

不缩进#define的好处是什么?如果我缩进它会不会让我成为一个坏人?这不是更好吗?

#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
Run Code Online (Sandbox Code Playgroud)

小智 99

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

如今,ANSI-C之前的编译器不存在.使用哪种样式("#"之前的空格或"#"之间的空格和标识符之间的空格).

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


Pat*_*ter 24

正如一些人已经说过的,一些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
Run Code Online (Sandbox Code Playgroud)

我经常在旧的Unix标题中看到这种风格,但我讨厌它,因为语法着色经常在这样的代码上失败.我使用非常明显的颜色作为预处理器指令,以便它们脱颖而出(它们处于元级别,因此不应该成为正常代码流的一部分).您甚至可以看到SO没有以有用的方式为序列着色.


Jon*_*ler 16

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

/* */ # /* */ include /* */ <stdio.h> /* */
Run Code Online (Sandbox Code Playgroud)

相当于:

#include <stdio.h>
Run Code Online (Sandbox Code Playgroud)

无论好坏,具有'-std = c89 -pedantic'的GCC 3.4.4无论如何都接受带注释的行.我不是在提倡这种风格 - 不是一秒钟(它是可怕的).我只是认为这是可能的.

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

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

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

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

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

第6.10节预处理指令说:

预处理指令由一系列预处理令牌组成,这些令牌以#预处理令牌开头(在转换阶段4开始时)是源文件中的第一个字符(可选地,在不包含换行符的空格之后)或者跟随包含至少一个换行符的空格,并以下一个换行符结束.

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

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

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


Mic*_*urr 7

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

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


Jar*_*Par 5

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

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

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

  • 这段代码看起来很奇怪的原因是因为你创建了两个缩进"流".我会将第4行缩进一个级别,然后我会将第6和第7行缩进两个级别. (12认同)
  • 我非常努力地安排我的代码,以便在我有实际代码的部分中有*no*`#ifdef`行.相反,如果我需要有条件的东西,我要么把它放在分解函数或分解宏中; 我找到的方式更清晰(好吧,至少对我而言).理想的情况是,所有这些提取出来的部分会在其他文件(头或有条件地编译源文件;通常的"条件"是什么平台的代码被用于建造). (3认同)
  • 完全同意.我有时甚至把括号放在#if看起来就像是if. (2认同)
  • 我会将第4行缩进一级,第6和第7行缩进两级. (2认同)