C相互引用静态初始值设定项

时间:2012-10-02 21:26:43

标签: c gcc static initialization

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*/

谢谢

3 个答案:

答案 0 :(得分:5)

尽管volatilestatic有关,但您发布的代码完全有效C.它使用了一个名为暂定词的特定于C的功能。此功能可确保您的程序中只有一个BB的两个定义都定义了相同的实体。没有什么“令人反感”的。

从夹板获得的警告无效。在C ++语言中,这确实构成了多重定义错误,但在C语言中却没有。关于extern的评论在C语言的上下文中没有任何意义。

答案 1 :(得分:3)

这没有意义。

编辑:

是的,'extern'没有必要(谢谢,AndreyT和Ada​​m 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的地址。

假设AB具有以下内存地址:

&A == 0xAAAAAAAA
&B == 0xBBBBBBBB

第3行中的代码执行以下操作:

A = 0xBBBBBBBB;

然后在第4行,它执行以下操作:

B = 0xAAAAAAAA;

现在,如果您要取消引用AB,您将获得以下内容(请注意,您必须首先转换为可解除引用的指针类型):

*A --> 0xAAAAAAAA
*B --> 0xBBBBBBBB

这完全有效,但可能不是您打算对您的代码执行的操作。

请记住,有两个不同的值在起作用。首先是指针的值。第二个是指针的地址。

您需要使用extern的唯一原因是使用另一个目标文件中定义的变量(即在file1.c中要使用file2.c中定义的全局变量) 。应用于全局变量时,static关键字表示变量为 file-static ,或者只能在该文件中使用。所以这两者显然是相互矛盾的。