Indenting #defines

I know that #defines, etc. are normally never indented. Why?

I'm working in some code at the moment which has a horrible mixture of #defines, #ifdefs, #elses, #endifs, etc. All these often mixed in with normal C code. The non-indenting of the #defines makes them hard to read. And the mixture of indented code with non-indented #defines is a nightmare.

Why are #defines typically not indented? Is there a reason one wouldn't indent (e.g. like this code below)?

#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
29349 次浏览

目前我正在编写一些代码,它们混合了 # Definition、 # ifdefs、 # elses、 # endfs 等等。所有这些常常与普通的 C 代码混合在一起。不缩进的 # Definition 使得它们很难阅读。缩进的代码和非缩进的 # Definition 的混合是一场噩梦。

一个常见的解决方案是对指令进行注释,这样您就可以很容易地知道它们指的是什么:

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


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

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

至于是不是好款式。就我个人而言,我喜欢把它们都放在左边。这样你就可以在一个固定的地方找到他们。是的,当有非常嵌套的宏时,它会变得很烦人。但是如果您缩进它们,最终将得到更奇怪的代码。

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

对于您给出的示例,可以使用缩进来使其更加清晰,因为您有如此复杂的嵌套指令结构。

就我个人而言,我认为在大多数情况下保持它们不缩进是有用的,因为这些指令与代码的其余部分是分开运行的。像 # ifdef 这样的指令是由预处理器处理的,在编译器看到你的代码之前,所以在 # ifdef 指令之后的代码块甚至可能不是 compiled

在指令与代码的其余部分之间保持视觉上的分离更为重要,因为它们与代码相互交错(而不是像您给出的示例那样,是一个专用的指令块)。

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

前 ANSI C 编译器这些天是不存在的。使用任何您喜欢的样式(“ #”之前的空格或“ #”和标识符之间的空格)。

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

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

有一件事一直在阻碍我(有时候甚至说服我停止尝试) ,那就是许多或大多数编辑器/IDE 只要稍有异议就会把指令扔到第1列。真是烦死人了。

关于解析预处理器指令,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. [Line splicing - removing backslash newline]

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

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

第6.10节预处理指令说:

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

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

As others have noted, the pre-standard C preprocessors did not behave uniformly in a number of ways, and spaces before and in preprocessor directives was one of the areas where different compilers did different things, including not recognizing preprocessor directives with spaces ahead of them.

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

正如一些人已经说过的,一些 Pre-ANSI 编译器要求 # 作为行中的第一个字符,但是他们并不要求将 de preProcessing 指令附加到它上面,所以缩进就是这样做的。

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

In almost all the currently available C/CPP compilers it is not restricted. It's up to the user to decide how you want to align code. 编程愉快。

我知道这是一个老话题,但我浪费了几天的时间寻找解决方案。我同意最初的观点,如果有很多这样的代码,那么就会使代码更清晰(在我的例子中,我使用指令来启用/禁用详细日志记录)。最后,我找到了可以工作于 VisualStudio2017的解决方案 给你

如果你喜欢缩进 # 杂注表达式,你可以在下面启用它: Tools > Options > Text Editor > C/C + + > Formatting > 缩进 > 预处理器指令的位置 > 保持缩进

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