#define变量的类型

时间:2011-12-21 02:20:08

标签: c c-preprocessor

如果我有:

#define MAXLINE    5000

MAXLINE被理解为什么类型?我应该假设它是int吗?我能以某种方式测试吗?

一般来说,如何确定#define ed变量的类型?

7 个答案:

答案 0 :(得分:42)

它没有类型。这是一个简单的文本替换。在MAXLINE作为令牌出现的任何地方,文本5000都将被删除。

例如:

int a = MAXLINE;

会将值5000放在a

虽然

char *MAXLINE2 = "MAXLINE";

不会导致

char *50002 = "5000";

所以,如果你想要进行类型检查,那么宏不可行。您将需要声明静态常量,这样类型检查由编译器完成。

有关staticconst#define之间差异的信息,有很多来源,包括这个问题:Static, define, and const in C

答案 1 :(得分:8)

(非常!)从广义上讲,您的C编译器在执行时将执行3个任务:

  1. 对源文件运行预处理传递

  2. 在预处理的源文件上运行编译器

  3. 在生成的目标文件上运行链接器。

  4. #开头的行,如

    
    #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
    

    (为了清楚起见,留下了注释,但通常由预处理器删除) 您可以在编译器上使用一个选项来检查预处理器的输出。在gcc中,-E选项将执行此操作。

    请注意,虽然预处理器没有类型概念,但没有理由不在宏中包含类型以保证完整性。 e.g。

    
    #define MAXLINE    ((int)5000)
    

答案 2 :(得分:5)

编译器永远不会看到那行代码,预处理器在实际编译之前运行,并用它们的文字值替换这些宏,请参阅下面的链接以获取更多信息

http://www.cplusplus.com/doc/tutorial/preprocessor/

答案 3 :(得分:3)

它没有类型。它只是在将代码传递给编译器之前预处理器将放入源代码的标记。你可以这样做(荒谬)来声明一个名为x5000的变量:

#define APPEND(x,y) x ## y

int main() {
        int APPEND(x,5000);
        x5000 = 3;
}

预处理器在将编译器正确传递给它之前将其转换为:

int main() {
        int x5000;
        x5000 = 3;
}

因此,仅仅因为您在宏中看到5000,并不意味着它必须以任何方式成为数字。

答案 4 :(得分:2)

MAXLINE根本不是变量。实际上,它不是C语法。编译过程的一部分在编译器之前运行预处理器,预处理器采取的一个操作是用MAXLINE之后的任何内容替换源文件中的#define MAXLINE标记的实例(问题代码中为5000) )。

除此之外:在代码中使用预处理器的另一种常见方法是使用#include指令,预处理器只是替换为包含文件的预处理内容。

实施例

让我们看一下运行中的编译过程的示例。这是一个文件foo.c,将在示例中使用:

#define VALUE 4

int main()
{
  const int x = VALUE;
  return 0;
}

我使用gcccppthe 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存在于源中,但未在任何地方定义。

答案 5 :(得分:1)

我们称之为宏或预处理器,用于字符串替换源文件内容。阅读:https://en.wikipedia.org/wiki/C_macro

答案 6 :(得分:1)

是的,您可以认为它是int

嗯,实际上所有其他答案都是正确的。它不是C,它只是 一个指令,告诉预处理器做一些文本 替换,因此它没有类型。但是,如果你不做任何事情 用它来制作时髦的东西(比如##预处理器技巧),你会的 通常使用MAXLINE像某种常量和预处理器 将用5000替换它,这确实是一个显式常量。和 常量确实有类型:5000int。写成的常量 十进制整数,没有后缀(如U或L),将被解释 编译器为intlong intunsigned long int:第一个 这些类型适合。

但这当然与预备版无关。你可以 将您的问题重写为“5000的类型是什么?”,没有 #define