我想访问表单的几个变量:
int arr1=1;
int arr2=1;
int arr3=1;
所以我写了
#define arr(i) arr##i
但是下面的代码不能像我预期的那样工作
#include <stdio.h>
int main(){
int arr1=1;
int arr2=1;
int arr3=1;
int j;
for(j=1; j<3; j++)
printf("%d",arr(j));
return 0;
}
你不可以做这个。在 C 中,变量名在运行时不存在。
您的宏将扩展为arrj
,这是一个未定义的变量名。使用适当的数组:
int arr[] = { 1, 1, 1 };
然后 print arr[j]
,但像这样循环:
for(j = 0; j < sizeof arr / sizeof *arr; ++j)
printf("%d\n, arr[j]);
宏代码用于预处理器阶段而不是运行时阶段
如果您使用gcc -E
. 您将看到您的代码等效于:
int main(){
int arr1=1;
int arr2=1;
int arr3=1;
int j;
for(j=1; j<3; j++)
printf("%d",arrj);
return 0;
}
当您构建程序时,gcc 从您的 c 代码生成另一个 c 代码,并在其中将代码中的所有宏替换为宏内容(此阶段称为预处理器阶段)。然后生成asm代码,然后生成二进制文件。
gcc -E
您可以通过: code of preprocessor phase查看生成的 c 代码(来自您的代码)
因此,这将产生arrj
结果。
C 的宏阶段是在程序运行之前发生的事情,甚至在它被解析为实际的 C 之前。
很久以前,预处理器是一个完全独立的程序,对 C 语言知之甚少。
像今天的大多数编译器一样,cc
当时只是运行不同的阶段。在它运行编译器、汇编器和链接器之前,它运行cpp
了C 预处理器。
而cpp只是解析定义,然后扩展宏,然后退出。然后cc将运行编译器。如今,宏扩展内置于编译器中,但它根据原始设计处理程序的文本输入。
今天在某些系统上仍然有一个/usr/bin/cpp
,但它通常只是一个运行编译器映像的 shell 脚本,带有选项说不编译。