【发布时间】:2012-01-24 22:39:21
【问题描述】:
如果我有:
#define MAXLINE 5000
MAXLINE 被理解为什么类型?我应该假设它是int 吗?我可以测试一下吗?
一般来说,如何确定#defineed 变量的类型?
【问题讨论】:
标签: c c-preprocessor
如果我有:
#define MAXLINE 5000
MAXLINE 被理解为什么类型?我应该假设它是int 吗?我可以测试一下吗?
一般来说,如何确定#defineed 变量的类型?
【问题讨论】:
标签: c c-preprocessor
它没有类型。这是一个简单的文本替换。文本 5000 将被放置在 MAXLINE 作为标记出现的任何位置。
例如:
int a = MAXLINE;
会将值 5000 放入 a。
虽然
char *MAXLINE2 = "MAXLINE";
不会导致
char *50002 = "5000";
因此,如果您想要进行类型检查,那么宏不是可行的方法。您将需要声明静态常量,这样编译器就会完成类型检查。
有关static、const和#define之间区别的信息,有很多来源,包括这个问题:Static, define, and const in C
【讨论】:
MAXLINE 根本不是变量。事实上,它不是 C 语法。编译过程的一部分在编译器之前运行预处理器,预处理器执行的操作之一是将源文件中的 MAXLINE 标记的实例替换为 #define MAXLINE 之后的任何内容(问题代码中的 5000)。
另外:在代码中使用预处理器的另一种常见方式是使用 #include 指令,预处理器只需将其替换为包含文件的预处理内容。
让我们看一个实际的编译过程示例。这是一个文件foo.c,将在示例中使用:
#define VALUE 4
int main()
{
const int x = VALUE;
return 0;
}
我使用gcc 和cpp (the C preprocessor) 作为示例,但是您可以使用任何编译器套件来执行此操作,当然,使用不同的标志。
首先,让我们编译foo.c 和gcc -o foo.c。发生了什么?有效;你现在应该有一个可执行文件foo。
您可以告诉gcc 只进行预处理而不进行任何编译。如果您执行gcc -E foo.c,您将获得标准输出的预处理文件。这是它产生的结果:
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo.c"
int main()
{
const int x = 4;
return 0;
}
注意main 的第一行已将VALUE 替换为4。
您可能想知道前四行是什么。这些被称为线标记,您可以在Preprocessor Output 中阅读有关它们的更多信息。
据我所知,您不能直接跳过 gcc 中的预处理,但是有几种方法可以告诉它文件已经被预处理。但是,即使您这样做,它也会删除文件中存在的宏,因为它们不是供编译器使用的。您可以使用gcc -E -fpreprocessed foo.c 查看编译器在这种情况下的作用:
.
.
.
.
int main()
{
const int x = VALUE;
return 0;
}
注意:我把点放在顶部;假装那些是空行(我不得不把它们放在那里让这些行被 SO 显示)。
这个文件显然不会编译(尝试gcc -fpreprocessed foo.c 找出答案)因为VALUE 存在于源代码中,但未在任何地方定义。
【讨论】:
我们称之为宏或预处理器,用于对源文件内容进行字符串替换。阅读:https://en.wikipedia.org/wiki/C_macro
【讨论】:
编译器永远不会看到那行代码,预处理器会在实际编译之前运行,并将这些宏替换为它们的字面值,有关更多信息,请参见下面的链接
【讨论】:
它没有类型。它只是一个标记,预处理器在将代码传递给编译器之前将其放入源代码中。你可以做这个(荒谬的)事情来声明一个名为x5000的变量:
#define APPEND(x,y) x ## y
int main() {
int APPEND(x,5000);
x5000 = 3;
}
预处理器在将其传递给编译器之前将其转换为 this:
int main() {
int x5000;
x5000 = 3;
}
因此,仅仅因为您在宏中看到 5000,并不意味着它必须是数字。
【讨论】:
(非常!)广义地说,您的 C 编译器在执行时将执行 3 个任务:
对源文件运行预处理传递,
在预处理的源文件上运行编译器
在生成的目标文件上运行链接器。
以# 开头的行,如行
#define MAXLINE 5000
由预处理器阶段处理。 (简单地说)预处理器将解析文件并对其检测到的任何宏执行文本替换。预处理器中没有类型的概念。
假设您的源文件中有以下几行:
#define MAXLINE 5000
int someVariable = MAXLINE; // line 2
char someString[] = "MAXLINE"; // line 3
预处理器将在第 2 行检测到宏 MAXLINE,并将执行文本替换。请注意,第 3 行 "MAXLINE" 不被视为宏,因为它是字符串文字。
预处理阶段完成后,编译阶段只会看到以下内容:
int someVariable = 5000; // line 2
char someString[] = "MAXLINE"; // line 3
(为清楚起见,cmets 已保留,但通常由预处理器删除)
您可能可以在编译器上使用一个选项来检查预处理器的输出。在 gcc 中,-E 选项将执行此操作。
请注意,虽然预处理器没有类型的概念,但没有理由不能在宏中包含类型以确保完整性。例如
#define MAXLINE ((int)5000)
【讨论】:
是的,您可以假设它是int。
嗯,实际上所有其他答案都是正确的。不是C,只是
告诉预处理器做一些文本的指令
替换,因此它没有类型。但是,如果您不执行任何操作
用它做一些时髦的事情(比如##预处理器技巧),你会
通常使用MAXLINE 像某种常量,以及预处理器
将用5000 替换它,这确实是一个显式常量。和
常量确实有类型:5000 是 int。一个常数写成
十进制整数,没有后缀(如 U 或 L),将被解释为
编译器为int、long int 或unsigned long int:第一个
这些类型中最适合的。
但这当然与前任无关。你可以
将您的问题改写为“5000 的类型是什么?”,没有
#define.
【讨论】: