C语言 缩进#定义

tv6aics1  于 2023-11-16  发布在  其他
关注(0)|答案(9)|浏览(97)

我知道#define s等通常不会缩进,为什么?
我现在正在处理一些代码,这些代码混合了#define s,#ifdef s,#else s,#endif s等。所有这些代码经常与正常的C代码混合在一起。#define s的非缩进使它们很难阅读。而缩进代码与非缩进的#define s的混合是一场噩梦。
为什么#define s通常不缩进?是否有原因不缩进(例如,像下面的代码)?

#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

字符串

9njqaruj

9njqaruj1#

前ANSI C预处理器不允许行首和“#”字符之间有空格;前导的“#”必须总是放在第一列。
现在已经没有ANSI之前的C编译器了。使用你喜欢的样式(“#”之前的空格或“#”和标识符之间的空格)。
http://www.delorie.com/gnu/docs/gcc/cpp_48.html

ig9co6j1

ig9co6j12#

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

8e2ybdfx

8e2ybdfx3#

关于预处理器指令的解析,C99标准(以及之前的C89标准)明确了编译器逻辑上执行的操作序列。特别是,我认为这意味着以下代码:

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

字符串
相当于:

#include <stdio.h>


不管怎样,GCC 3.4.4中的“-std=c89 -pedantic”接受了这条充满注解的代码。我并不是在提倡这种风格--一点也不(这太可怕了)。我只是认为这是可能的。
ISO/IEC 9899:1999部分5.1.1.2翻译阶段说:
1.[字符Map,包括三字符]
1.[行拼接-删除反斜杠换行符]
1.源文件被分解为预处理标记和空白字符序列(包括注解)。源文件不应以部分预处理标记或部分注解结束。每个注解由一个空格字符替换。保留新行字符。除了新行之外的每个非空空白字符序列是保留还是由一个空格字符替换是实现定义的。
1.执行预处理指令,扩展宏调用,[...]
第6.10节预处理指令说:
预处理指令由一系列预处理标记组成,该标记以# preprocessing标记开始,(在翻译阶段4开始时)是源文件中的第一个字符(可选地在不包含换行符的白色空格之后)或在包含至少一个换行符的白色空格之后,并以下一个换行符结束。
唯一可能的争议是括号表达式“(at the start of translation phase 4)”,这可能意味着哈希之前的注解必须不存在,因为它们在第4阶段结束之前不会被空格替换。
正如其他人所指出的那样,标准前的C预处理器在许多方面的行为并不一致,预处理器指令之前和中的空格是不同编译器做不同事情的领域之一,包括不识别前面有空格的预处理器指令。
值得注意的是,反斜杠-换行符删除发生在注解被分析之前。因此,你不应该用反斜杠结束//注解。

bmvo0sr5

bmvo0sr54#

我不知道为什么它不是更常见的。当然有时候我喜欢修改预处理器指令。
有一件事一直在妨碍我(有时甚至说服我停止尝试),那就是许多或大多数编辑器/IDE会在最轻微的挑衅下将指令扔到第1列。

hwazgwia

hwazgwia5#

这些天来,我相信这主要是一个风格的选择。我认为在遥远的过去,不是所有的编译器都支持缩进预处理器定义的概念。我做了一些研究,无法支持这种说法。但无论如何,似乎所有现代编译器都支持缩进预处理器宏的想法。我没有C或C++的副本虽然标准,但我不知道这是否是标准行为。
至于它是否是好的风格。就个人而言,我喜欢把它们都放在左边的想法。它给了你一个一致的地方去寻找它们。是的,当有非常嵌套的宏时,它会变得很烦人。但是如果你把它们放在一起,你最终会得到更奇怪的代码。

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

字符串

rdlzhqv9

rdlzhqv96#

对于你给出的例子,使用缩进来使它更清晰可能是合适的,因为你有这样一个复杂的嵌套指令结构。
我个人认为在大多数情况下保持指令不缩进是有用的,因为这些指令与代码的其余部分分开操作。像#ifdef这样的指令是由预处理器处理的,在编译器看到你的代码之前,所以在#ifdef指令之后的代码块甚至可能不被编译。
当指令散布在代码中时(而不是像给予的示例中那样,使用一个专用的指令块),将指令与代码的其余部分在视觉上分开更为重要。

64jmpszr

64jmpszr7#

在几乎所有目前可用的C/CPP编译器中,它是不受限制的。它取决于用户决定如何对齐代码。所以快乐的编码。

lf5gs5x2

lf5gs5x28#

我现在正在处理一些代码,其中有一个可怕的混合#defines,#ifdef,#elses,#endifs,#等。所有这些经常与正常的C代码混合。#defines的非缩进使它们很难阅读。而缩进代码与非缩进的#defines的混合是一场噩梦。
一个常见的解决方案是注解指令,这样你就可以很容易地知道它们指的是什么:

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

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

字符串

omqzjyyz

omqzjyyz9#

我知道这是一个老主题,但我浪费了几天的时间寻找解决方案。我同意最初的帖子,如果你有很多代码,我打算让代码更干净(在我的情况下,我使用指令来启用/禁用详细日志记录)。最后,我找到了解决方案here,它适用于Visual Studio 2017
如果你想修改#pragma表达式,你可以在下面启用它:工具>选项>文本编辑器> C/C++ >缩进>预处理器指令的位置>保持缩进
剩下的唯一问题是自动代码布局修复了格式化=(

相关问题