C中是否可以相互引用静态变量初始值设定项,如下例所示?
该示例在gcc -Wall中没有警告的情况下编译,如果将第2行添加到预先声明“B”。第2行是令人反感的,因为它也定义了B,第4行也是如此。带有-weak检查的夹板lint程序警告“B”被定义两次:“变量B被重新定义。重新定义了一个函数或变量。声明应该使用extern。“
通常使用extern关键字进行声明,但extern和static不能一起使用,也不能在gcc下编译。
#include <stdio.h> /*1*/
volatile static void * B; /*2*/
volatile static void * A = &B; /*3*/
volatile static void * B = &A; /*4*/
int main() /*5*/
{ /*6*/
printf("A = %x, B = %x\n", (int)A, (int)B); /*7*/
return 0; /*8*/
} /*9*/
谢谢
答案 0 :(得分:5)
尽管volatile
与static
有关,但您发布的代码完全有效C.它使用了一个名为暂定词的特定于C的功能。此功能可确保您的程序中只有一个B
:B
的两个定义都定义了相同的实体。没有什么“令人反感”的。
从夹板获得的警告无效。在C ++语言中,这确实构成了多重定义错误,但在C语言中却没有。关于extern
的评论在C语言的上下文中没有任何意义。
答案 1 :(得分:3)
这没有意义。
编辑:
是的,'extern'没有必要(谢谢,AndreyT和Adam Rosenfield),但&B
的类型为void**
,而不是void*
。
当然,void**
投放到void*
,但有什么意义呢?如果你想要别名或指针,那么只需要声明第三个变量“缓冲区”,然后在A和B中指向它。
unsigned char SomeBuffer[LENGTH];
void* A = SomeBuffer;
void* B = SomeBuffer;
答案 2 :(得分:0)
看起来你似乎正在定义一个循环循环,但事实上你并非如此。 C &
运算符是 address of of 运算符,并获取相关变量的地址。
正如@AndreyT指出的那样,第2行具有暂时定义 B
的效果,因此第3行知道它。您可以将第2行视为分配B
的内存位置,然后在第4行中将值放在那里。
代码在功能上与您编写如下代码相同:
volatile static void * A;
volatile static void * B;
int main()
{
A = &B;
B = &A;
printf("A = %x, B = %x\n", (int)A, (int)B);
return 0;
}
因此,在第3行中,您将A
定义为指向B
的地址。在第4行中,您定义B
以指向A
的地址。
假设A
和B
具有以下内存地址:
&A == 0xAAAAAAAA
&B == 0xBBBBBBBB
第3行中的代码执行以下操作:
A = 0xBBBBBBBB;
然后在第4行,它执行以下操作:
B = 0xAAAAAAAA;
现在,如果您要取消引用A
和B
,您将获得以下内容(请注意,您必须首先转换为可解除引用的指针类型):
*A --> 0xAAAAAAAA
*B --> 0xBBBBBBBB
这完全有效,但可能不是您打算对您的代码执行的操作。
请记住,有两个不同的值在起作用。首先是指针的值。第二个是指针的地址。
您需要使用extern
的唯一原因是使用另一个目标文件中定义的变量(即在file1.c
中要使用file2.c
中定义的全局变量) 。应用于全局变量时,static
关键字表示变量为 file-static ,或者只能在该文件中使用。所以这两者显然是相互矛盾的。