有些时候我们需要预先声明一个静态变量,然后使用它。但是这个声明的变量名可能是错误的,编译器无法检测到它,哎呀!
范例:
/* lots of codes */
static some_type some_name; /* pre-declaration */
/* but it may define "some_name" */
/* use some_name */
/* lots of codes */
static some_type someName = initialization; /* definition */
/* use someName */
/* lots of codes */
字符串
“some_name”和“someName”是不同的,我们在开始使用了一个错误的变量。如果预声明语句没有定义任何东西,编译器会发现错误。
那么,如何声明一个静态变量而不定义它呢?如何将预声明改为一个新的,使编译器可以检测到错误的名称?
7条答案
按热度按时间qvtsj1bj1#
gcc
将在您描述的情况下给出给予警告:字符串
解决方案:做你现在正在做的事情,但不要忽略编译器警告;)
编辑:
关于你更新的问题:不,我不相信有一种方法可以简单地声明一个静态变量(而不定义它)。
常见的解决方案是确保所有的全局作用域变量只声明一次,如果需要,可以使用初始化器。
1cosmwyk2#
字符串
静态变量some_name已经初始化为0;它是定义,而不仅仅是声明。
IMO,静态变量不能在C中使用外部说明符声明,因为它的链接总是内部的。
kxkpmulp3#
在C语言中,不可能为具有内部链接的对象创建非定义声明(即术语中的“预声明”)。
最接近的是一个 * 临时定义 *,这就是你在例子中所做的。但是如果输入错误,临时定义将隐含地产生一个独立的定义,而不是链接器错误。
v6ylcynt4#
一点背景:
正如其他人所指出的,静态变量是有内部链接的,这意味着它们只能在同一个“编译单元”或源文件中使用。这意味着你不能在头文件中声明它,在一个编译单元中赋值,然后期望这个值出现在另一个编译单元中。
当你初始化一个全局变量(静态或非静态)时,编译器只是将初始值放入可执行文件中为变量分配的内存位置。换句话说,它总是有一个初始值。当然,你总是可以在以后使用赋值语句重写该值。
建议:
如果你在编译时真的不知道变量的值,那么你应该在初始化函数中动态地赋值。
字符串
如果你想在一个地方声明变量,比如头文件,并在源文件中定义它,那么你应该使用“extern”声明,它告诉编译器不用担心变量在哪里。链接器会找到变量的位置,就像它在另一个文件中找到一个函数一样,并填写地址。
标题:
型
源文件1:
型
源文件2:
型
如果你只想在一个地方声明变量,在另一个地方定义它,不要使用'static'关键字。这样做的缺点是,你不能在不同的编译单元(.c文件)中使用同一个全局变量,也不能在头文件中使用它。
ttcibm8c5#
你需要预先声明变量吗?如果不需要,那么把初始化器放在唯一的声明上。如果你的初始化器不是一个常量(这需要C++,而不是C,IIRC),那么我可以理解为什么你需要在使用它的一些函数之前预先声明它。但是这样你需要的初始化器的所有东西都可以在它之前预先声明。
所以把常量def和静态变量放在每个文件的顶部,这样静态变量的初始化器就可以放在常量后面,这样就不需要单独的初始化行了。
在任何其他情况下,caf都是对的:用gcc编译代码只是为了获得它的警告的好处,这是值得的。我已经为g用C编写的MFC GUI做了这件事。(编译,而不是运行!)
AFAIK C没有办法编写弱定义,如果后面没有带有初始化器的定义,则会产生错误。始终存在隐式0,因为变量位于BSS部分。
q7solyqu6#
在C++中(而不是C),可以使用未命名的命名空间而不是
static
.Decliter来完成,如下所示:字符串
extern
没有定义,但由于未命名的名称空间,some_name
无论如何都有内部链接,就像声明为static
一样(参考:https://en.cppreference.com/w/cpp/language/storage_duration#Linkage)。相应的定义很简单:
型
ki1q1bka7#
如果我理解你的问题,也许你只是没有正确地面对它。
如果你用
extern SomeType someVar_;
会更好,它对你的程序说,我知道这个变量是已知的,但我现在不想告诉你它是什么。因此,您可以在一个单独的文件中声明您的变量,
static SomeType SomeVar_;
个在你的档案里,
extern SomeType SomeVar_
个然后把初始化放在你想要的任何地方。