为什么#define不需要分号?

Sha*_*ash 18 c c-preprocessor

我在C中编写了一些测试代码.我错误地插入了;一个#define,这给了我错误.为什么#defines 不需要分号?

进一步来说 :

方法1:有效

const int MAX_STRING = 256;

int main(void) {
    char buffer[MAX_STRING];
}
Run Code Online (Sandbox Code Playgroud)

方法2:不起作用 - 编译错误.

#define MAX_STRING 256;

int main(void) {
    char buffer[MAX_STRING];
}
Run Code Online (Sandbox Code Playgroud)

这些代码行为不同的原因是什么?这两个MAX_STRING都不是常量吗?

xen*_*ros 38

#define MAX_STRING 256;
Run Code Online (Sandbox Code Playgroud)

手段:

无论何时在预处理时找到MAX_STRING,请将其替换为256;.在你的情况下,它将使方法2:

#include <stdio.h>
#include <stdlib.h>
#define MAX_STRING 256;

int main(void) {
    char buffer [256;];
}
Run Code Online (Sandbox Code Playgroud)

这是无效的语法.更换

#define MAX_STRING 256;
Run Code Online (Sandbox Code Playgroud)

#define MAX_STRING 256
Run Code Online (Sandbox Code Playgroud)

两个代码之间的区别在于,在第一种方法中,您声明一个常量等于256但在您定义的第二个代码MAX_STRING中代表256;源文件中的代码.

#define指令用于定义预处理器在编译之前操作程序源代码所使用的值或宏.因为在编译器对源代码执行操作之前替换了预处理程序定义,所以#define引入的任何错误都很难跟踪.

语法是:

#define CONST_NAME VALUE
Run Code Online (Sandbox Code Playgroud)

如果最后有一个;,它被视为一部分VALUE.

要了解究竟#define是如何工作的,请尝试定义:

#define FOREVER for(;;)
...
    FOREVER {
         /perform something forever.
    }
Run Code Online (Sandbox Code Playgroud)

John Hascall的有趣评论:

大多数编译器会为您提供一种在预处理器阶段之后查看输出的方法,这可以帮助调试此类问题.

gcc它可以用旗帜完成-E.

  • 大多数编译器会为您提供一种在预处理器阶段之后查看输出的方法,这可以帮助调试此类问题. (5认同)

Jon*_*Jon 22

#define是一个预处理程序指令,而不是C语法定义的语句声明(两者都需要以分号结尾).每个语法的规则是不同的.


MBy*_*ByD 17

define 是一个预处理程序指令,并且是一个简单的替换,它不是一个声明.

BTW,作为替代品,它可能包含一些;作为其中的一部分:

// Ugly as hell, but valid 
#define END_STATEMENT ;

int a = 1 END_STATEMENT // preprocessed to -> int a = 1;
Run Code Online (Sandbox Code Playgroud)


AnT*_*AnT 13

两个常数?没有.

第一种方法不会在C语言中产生常量.Const限定变量不符合C中的常量.第一种方法的作用只是因为past-C99 C编译器支持可变长度数组(VLA).你buffer是第一种情况下的VLA,特别是因为MAX_STRING不是常数.尝试在文件范围内声明相同的数组,您将收到错误,因为文件范围中不允许使用VLA.

第二种方法可用于将名称分配给C中的常量值,但您必须正确执行.该;宏定义不应该存在.宏通过文本替换工作,您不希望将该额外内容替换;为数组声明.定义该宏的正确方法是

#define MAX_STRING 256
Run Code Online (Sandbox Code Playgroud)

在C语言中,当涉及到定义适当的命名常量时,基本上只限于宏和枚举.不要试图使用const"常量",除非你真的知道它将适用于你的目的.


Bat*_*eba 11

就语言而言,第二个版本没有定义常量,只是一个文本块的替换规则.一旦预处理器完成了它的工作,编译器就会看到

char buffer [256;];

这在语法上是无效的.

故事的寓意:更喜欢这种const int MAX_STRING = 256;方式,因为它可以帮助您,编译器和调试器.

  • 一般情况下`const int MAX_STRING = 256;`是*不是*在C语言中可行的方法,因为这样的'MAX_STRING`在C中不是*常量*并且不允许在需要常量表达式的地方使用. (5认同)
  • 您曾尝试使用宏调试一堆代码吗? (3认同)
  • @Bathsheba:VLA并没有真正挽救这一天.还有很多其他的上下文,其中C需要常量:case标签,非局部数组声明,位域宽度,静态初始化器等.这些上下文都不会接受`const int`"常量".换句话说,每个需要编译时值的上下文都会拒绝`const int`,因为在C中这不被认为是编译时的值. (3认同)

Alo*_*ave 10

因为这就是预编译器指令的语法决定方式.

只有语句;以c/c ++ 结尾,#define是一个预处理器指令而不是语句.