4

在阅读了一些 K&R 的 The C Programming Language 之后,我发现了#define 符号常量。我决定定义...

#define INTEGER_EXAMPLE 2
#define CHAR_EXAMPLE 2

...所以我的问题是 C 如何知道我是在定义 int 还是 char 类型?

4

7 回答 7

9

#define-d 名称没有类型。他们只是定义文本替换。

编译器看到的是预处理的形式。如果使用 GCC,请尝试gcc -C -E somesource.c查看(预处理的)输出。

在 1980 年代,预处理器是一个单独的程序。

阅读有关cpp预处理器、预处理器C 预处理器wikipages 的信息。

您甚至可以定义定义不明确的名称,例如

#define BAD @*?$ some crap $?

更可怕的是,你可以定义语法不完整的东西,比如

#define BADTASTE 2 +

和后来的代码BADTASTE 3

实际上,您想在定义宏时使用括号。如果你有

#define BADPROD(x,y) x*y

thenBADPROD(2+3,4+5)扩展为2+3*4+5编译器可以理解的范围2+ (3*4) +5;你真的想要

#define BETTERPROD(x,y) ((x)*(y))

所以BETTERPROD(2+3,4+5)扩展为((2+3)*(4+5))

避免宏参数中的副作用,例如BETTERPROD(j++,j--)

通常,请谨慎使用宏并让它们保持简单。

于 2013-10-15T10:52:24.547 回答
3

#define STRING VALUE

只是预处理器用 VALUE 替换 STRING 的指令,之后编译器将控制并检查类型

于 2013-10-15T10:54:01.633 回答
3

关于这些定义,它没有,扩展的宏没有类型。处理#define 的预处理器只是替换源代码中的文本

当您在某处使用这些定义时,例如

int i = INTEGER_EXAMPLE;

这将扩展到

int i = 2;

这里将文字 2(在此上下文中是一个 int)分配给一个 int。

你也可以这样做:

char c = INTEGER_EXAMPLE;

在这里,文字 2 也是一个 int,它被分配给一个 char。2 虽然在 char 的范围内,所以一切正常。

你甚至可以这样做:

int INTEGER_EXAMPLE = 2;

这将扩展到

int 2 = 2;

这不是有效的 C.

于 2013-10-15T10:55:02.950 回答
2

不是,这是预处理器。常量的类型取决于使用它的上下文。例如:

#define INT_EXAMPLE 257

char foo = INT_EXAMPLE;

将尝试在 char 上下文中分配 257 ,除非char您的计算机上有超过 8 位,否则应该会生成警告。

于 2013-10-15T10:55:12.173 回答
2

#定义只不过是值的文字替换。您可能想使用

static const

因为它尊重范围并且是类型安全的。尝试这个:

#define main no_main

int main()  // gets replaced as no_main by preprocessor
{
    return 0;
}

应该给你链接错误。或者你可以试着以此来愚弄你的老师

#define I_Have_No_Main_Function main //--> Put this in header file 1.h

#include"1.h"

int I_Have_No_Main_Function()
{
    return 0;
}
于 2013-10-15T10:56:18.203 回答
1

它没有。这些#define语句在编译器开始工作之前被处理。基本上,预处理器会搜索和替换您编写的内容并替换它,例如,所有实例INTEGER_EXAMPLE都替换为 string 2

由编译器根据它的使用位置来决定它的类型2

int x = INTEGER_EXAMPLE; // 2 is an integer
char y = INTEGER_EXAMPLE; // 2 is a char
于 2013-10-15T10:54:12.137 回答
1

预处理器无法知道宏定义的类型。预处理器只会将所有出现的 'CHAR_EXAMPLE' 替换为 '2'。我会使用演员表:

#define CHAR_EXAMPLE ((char)2)
于 2013-10-15T10:55:10.427 回答