缩进#define

发布于 2024-07-17 18:50:26 字数 969 浏览 6 评论 0原文

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

我目前正在编写一些代码,其中混合了 #define#ifdef#else、< code>#endif 等。所有这些通常与普通 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

吖咩 2024-07-24 18:50:26

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

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

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

Pre-ANSI C preprocessor did not allow for space between the start of a line and the "#" character; the leading "#" had to always be placed in the first column.

Pre-ANSI C compilers are non-existent these days. Use which ever style (space before "#" or space between "#" and the identifier) you prefer.

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

正如一些人已经说过的,一些 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 没有以有用的方式为序列着色。

As some have already said, some Pre-ANSI compilers required the # to be the first char on the line but they didn't require the preprocessor directive to be attached to it, so indentation was made this way.

#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

I've often seen this style in old Unix headers but I hate it as the syntax coloring often fails on such code. I use a very visible color for pre-processor directives so that they stand out (they are at a meta-level so should not be part of the normal flow of code).
You can even see that SO does not color the sequence in a useful manner.

八巷 2024-07-24 18:50:26

关于预处理器指令的解析,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 预处理器在许多方面的行为并不统一,预处理器指令之前和之中的空格是不同编译器执行不同操作的领域之一,包括不识别前面带有空格的预处理器指令。

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

Regarding the parsing of preprocessor directives, the C99 standard (and the C89 standard before it) were clear about the sequence of operations performed logically by the compiler. In particular, I believe it means that this code:

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

is equivalent to:

#include <stdio.h>

For better or worse, GCC 3.4.4 with '-std=c89 -pedantic' accepts the comment-laden line, at any rate. I'm not advocating that as a style - not for a second (it is ghastly). I just think that it is possible.

ISO/IEC 9899:1999 section 5.1.1.2 Translation phases says:

  1. [Character mapping, including trigraphs]

  2. [Line splicing - removing backslash newline]

  3. The source file is decomposed into preprocessing tokens and sequences of
    white-space characters (including comments). A source file shall not end in a
    partial preprocessing token or in a partial comment. Each comment is replaced by
    one space character. New-line characters are retained. Whether each nonempty
    sequence of white-space characters other than new-line is retained or replaced by
    one space character is implementation-defined.

  4. Preprocessing directives are executed, macro invocations are expanded, [...]

Section 6.10 Preprocessing directives says:

A preprocessing directive consists of a sequence of preprocessing tokens that begins with
a # preprocessing token that (at the start of translation phase 4) is either the first character
in the source file (optionally after white space containing no new-line characters) or that
follows white space containing at least one new-line character, and is ended by the next
new-line character.

The only possible dispute is the parenthetical expression '(at the start of translation phase 4)', which could mean that the comments before the hash must be absent since they are not otherwise replaced by spaces until the end of phase 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.

It is noteworthy that backslash-newline removal occurs before comments are analyzed.
Consequently, you should not end // comments with a backslash.

梦毁影碎の 2024-07-24 18:50:26

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

一直困扰我的一件事(有时说服我停止尝试)是,许多或大多数编辑器/IDE 都会在最轻微的挑衅下将指令扔到第 1 列。 这真是太烦人了。

I don't know why it's not more common. There are certainly times when I like to indent preprocessor directives.

One thing that keeps getting in my way (and sometimes convinces me to stop trying) is that many or most editors/IDEs will throw the directive to column 1 at the slightest provocation. Which is annoying as hell.

野却迷人 2024-07-24 18:50:26

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

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

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

These days I believe this is mainly a choice of style. I think at one point in the distant past, not all compilers supported the notion of indenting preprocessor defines. I did some research and was unable to back up that assertion. But in any case, it appears that all modern compilers support the idea of indenting pre-processor macro. I do not have a copy of the C or C++ standard though so I do not know if this is standard behavior or not.

As to whether or not it's good style. Personally, I like the idea of keeping them all to the left. It gives you a consistent place to look for them. Yeah it can get annoying when there are very nested macros. But if you indent them, you'll eventually end up with even weirder looking code.

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif
天生の放荡 2024-07-24 18:50:26

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

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

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

For the example you've given it may be appropriate to use indentation to make it clearer, seeing as you have such a complex structure of nested directives.

Personally I think it is useful to keep them not indented most of the time, because these directives operate separately from the rest of your code. Directives such as #ifdef are handled by the pre-processor, before the compiler ever sees your code, so a block of code after an #ifdef directive may not even be compiled.

Keeping directives visually separated from the rest of your code is more important when they are interspersed with code (rather than a dedicated block of directives, as in the example you give).

硬不硬你别怂 2024-07-24 18:50:26

目前几乎所有可用的 C/CPP 编译器都没有限制。 由用户决定如何对齐代码。
编码如此快乐。

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.
So happy coding.

梦在深巷 2024-07-24 18:50:26

我现在正在编写一些代码,其中混合了#defines、#ifdefs、#elses、#endifs、#etc。 所有这些经常与普通的 C 代码混合在一起。 #defines 的非缩进使得它们难以阅读。 缩进代码与非缩进#defines 的混合是一场噩梦。

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

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

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

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.

A common solution is to comment the directives, so that you easily know what they refer to:

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

#ifndef FOO
/* a lot of code */
#endif /* not FOO */
睡美人的小仙女 2024-07-24 18:50:26

我知道这是老话题,但我浪费了几天时间寻找解决方案。 我同意最初的文章,如果你有很多代码,那么打算使代码更清晰(在我的例子中,我使用指令来启用/禁用详细日志记录)。 最后,我在此处找到了适用于 Visual Studio 2017 的解决方案

如果您想缩进#pragma 表达式,您可以在“工具”>“工具”下启用它。 选项> 文本编辑器> C/C++> 格式化> 压痕> 预处理器指令的位置> 保留缩进

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

I know this is old topic but I wasted couple of days searching for solution. I agree with initial post that intending makes code cleaner if you have lots of them (in my case I use directives to enable/disable verbose logging). Finally, I found solution here which works Visual Studio 2017

If you like to indent #pragma expressions, you can enable it under: Tools > Options > Text Editor > C/C++ > Formatting > Indentation > Position of preprocessor directives > Leave indented

The only problem left is that auto code layout fixed that formatting =(

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文