缩进#defines

时间:2009-04-25 14:56:30

标签: c coding-style indentation c-preprocessor code-formatting

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

我目前正在处理一些代码,这些代码混合了#define s,#ifdef s,#else s,#endif s等等。这些通常与普通的C代码混合在一起。 #define的非缩进使得它们难以阅读。缩进代码与非缩进#define的混合是一场噩梦。

不缩进#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

9 个答案:

答案 0 :(得分:96)

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

现在,ANSI-C之前的编译器不存在。使用哪种风格(“#”之前的空格或“#”与标识符之间的空格)。

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

答案 1 :(得分: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

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

答案 2 :(得分:16)

关于预处理程序指令的解析,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. [行拼接 - 删除反斜杠换行符]

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

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

  8.   

第6.10节预处理指令说:

  

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

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

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

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

答案 3 :(得分:6)

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

有一件事一直妨碍我(有时候说服我不要再去尝试),很多或大多数编辑/ IDE都会在最轻微的挑衅下将指令抛给第1列。这真令人讨厌。

答案 4 :(得分:5)

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

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

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

答案 5 :(得分:3)

对于您给出的示例,使用缩进可能更合适,因为您拥有嵌套指令的复杂结构。

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

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

答案 6 :(得分:2)

  

我正在使用一些代码,其中包含#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 */

答案 7 :(得分:1)

在几乎所有当前可用的C / CPP编译器中,它不受限制,由用户决定要如何对齐代码。 很高兴编写代码。

答案 8 :(得分:0)

我知道这是个老话题,但是我浪费了几天来寻找解决方案。我同意最初的帖子,即如果您有很多代码,它们可以使代码更整洁(就我而言,我使用指令来启用/禁用详细日志记录)。最后,我找到了适用于Visual Studio 2017的解决方案here

如果要缩进#pragma表达式,可以在以下位置启用它:工具>选项>文本编辑器> C / C ++>格式>缩进>预处理程序指令的位置>缩进

剩下的唯一问题是自动代码布局修复了该格式=(