缩进#define


99

我知道#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

Answers:


103

ANSI C之前的预处理器不允许在行首和“#”字符之间留空格;前导“#”必须始终放在第一列中。

如今,ANSI C之前的编译器不存在。使用您喜欢的样式(“#”前的空格或“#”与标识符之间的空格)。

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


26

就像一些人已经说过的那样,某些Pre-ANSI编译器要求#是该行的第一个字符,但是它们不需要附加de preprocessor指令,因此采用这种方式进行缩进。

#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不会以有用的方式为序列着色。


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. 执行预处理指令,扩展宏调用,[...]

第6.10节“预处理指令”指出:

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

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

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

值得注意的是,在分析评论之前会先删除反斜杠换行符。因此,您不应//以反斜杠结束注释。


7

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

一直困扰着我(有时甚至说服我停止尝试)的一件事是,许多或大多数编辑器/ IDE都会在丝毫挑衅的情况下将指令扔到第1列。真烦人。


5

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

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

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

14
这段代码看起来很怪异的原因是,您已经创建了两个缩进流。我会将第4行缩进一个级别,并将第6行和第7行缩进两个级别。
凯文·莱蒂

3
完全同意。有时我甚至放了括号,因此#if的外观就像if的外观。
baash05 2010年

3
我非常努力地安排我的代码,以便在我有实际代码的部分中没有任何 #ifdef行。相反,如果我需要条件性的东西,我要么将其放入分解函数中,要么放入分解宏中。我发现的方式更加清晰(嗯,至少对我而言)。理想情况下,所有那些分解出来的部分都将放在其他文件中(标头或有条件编译的源文件;通常的“条件”是为代码构建的平台)。
Donal Fellows 2010年

2
我会缩进第4行,第6行和第7行是两级。
Rocketmagnet

3

对于您给出的示例,考虑到嵌套指令的结构如此复杂,使用缩进使其更清晰可能是合适的。

我个人认为使大多数时候不缩进是很有用的,因为这些指令与其余代码分开工作。诸如#ifdef之类的指令是在编译器看到您的代码之前由预处理程序处理的,因此#ifdef指令之后的代码块甚至可能不会被编译

当指令散布在代码中时,使指令在视觉上与代码的其余部分保持更重要的位置(而不是像您提供的示例中那样,专用的指令块)。


3
从IP的角度来看,由于jmp的原因,未编译的内容与未达到的内容有什么区别。
baash05年

2

目前,我正在使用某些代码,其中包含#define,#ifdefs,#elses,#endifs,#etc的可怕组合。所有这些通常都与普通的C代码混合在一起。#define的非缩进使得它们难以阅读。缩进代码与非缩进#defines的混合是一场噩梦。

常见的解决方案是注释指令,以便您轻松知道它们指的是什么:

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

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

6
我已经看过这种风格,老板使用它。而且,就像他的其他代码一样,它只是一团糟。想象一下,从常规的if()语句中删除所有缩进,然后使用这些注释。您会抱怨您无法轻易看到他们指的是什么。
Rocketmagnet

2

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


1
体面的答案。您可以通过添加一些特定的样式指南参考来改进它吗?
EtherDragon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.