错误:X 可能在 C 中的此函数中未初始化使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/628410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
error: X may be used uninitialized in this function in C
提问by Eduardo
I am getting this error
我收到此错误
error: Access.Core may be used uninitialized in this function
And this is my code:
这是我的代码:
static int FirstTime = 1;
MyStruct Access;
if (FirstTime) {
FirstTime = 0;
Access = Implementation();
DoSomething(Access);
}
if(Other_Variable) {
Access = Implementation2();
DoSomething(Access);
}
//The Other_Variable will be set to 1 and to 0 by other part of the code
My code is like that because I want to call to the function Implementation only the first time. In every call the Access variable is going to be updated so it does not make many sense make it static.
我的代码是这样的,因为我只想第一次调用函数实现。在每次调用中,Access 变量都将被更新,因此将其设为静态没有多大意义。
If I make Access static works, but I do not like make it static because in every other call Access is going to be updated. Any way to avoid the problem without making it static?.
如果我将 Access 设为静态工作,但我不喜欢将其设为静态,因为在其他所有调用中,Access 都会更新。有什么方法可以在不使其静态的情况下避免问题?
Also any better options to execute only once a function instead of using a static variable are welcome.
也欢迎任何更好的选择只执行一次函数而不是使用静态变量。
回答by Johannes Schaub - litb
Make Access
like this (and remove FirstTime
and the if
):
做Access
这样的(和删除FirstTime
和if
):
static MyStruct Access = Implementation(this_b);
The reason you get this warning is because static variables survive one function call. Their value is retained across all function calls (withoutregard to which thread calls that function). So, FirstTime
will control whether you initialize Access
. The first time you call the function that code is in will correctly initialize the Access
variable. But with every further function call, FirstTime
is zero, and you will notinitialize Access
anymore, and thus will use an uninitialized variable down the code.
您收到此警告的原因是静态变量在一次函数调用中仍然存在。它们的值在所有函数调用中保留(不考虑哪个线程调用该函数)。所以,FirstTime
会控制你是否初始化Access
。第一次调用代码所在的函数时将正确初始化Access
变量。但是随着每次进一步的函数调用,它FirstTime
都为零,并且您将不再初始化Access
,因此将在代码中使用未初始化的变量。
Edit:Now, with your updated information, you say that you have two Implementation
functions. The first time you want to use one, and all the other times you want to use another function. How about this then:
编辑:现在,根据您的更新信息,您说您有两个Implementation
功能。第一次您想使用一个功能,而其他所有时间您都想使用另一个功能。那么这个怎么样:
// static will be false/zero by default
static bool AlreadyCalled;
MyStruct Access;
if (!AlreadyCalled) {
Access = Implementation();
AlreadyCalled = true;
} else {
Access = Implementation2();
}
Depending on your actual use case, there may be better ways to handle this, though. For example, why not update the state of Access
, like this:
不过,根据您的实际用例,可能有更好的方法来处理这个问题。例如,为什么不更新 的状态Access
,像这样:
// let the default constructor initialize it
// to a plausible state
static MyStruct Access;
// use RAII to update the state of Access when this
// function returns.
MyUpdater updater(Access);
// now, do whatever the function does.
Something like this for MyUpdater
:
像这样的东西MyUpdater
:
struct MyUpdater {
MyStruct &s;
MyUpdater(MyStruct &s):s(s) { }
~MyUpdater() {
s.ChangeState();
}
};
That pattern is called RAII
: You associate some useful action with the constructor and destructor of a locally allocated object.
该模式称为RAII
:您将一些有用的操作与本地分配对象的构造函数和析构函数相关联。
回答by Jonathan Leffler
@litb's answer is interesting. An equivalent program follows. The code compiles and works as stated in C++, but doesn't compile in C.
@litb 的回答很有趣。一个等效的程序如下。代码按照 C++ 中的说明进行编译和工作,但不能在 C 中编译。
#include <stdio.h>
static int newval(void) { return 3; }
void inc(void)
{
static int a = newval();
a++;
printf("%d\n", a);
}
int main(void)
{
int i;
for (i = 0; i < 10; i++)
inc();
return(0);
}
gcc says:
gcc 说:
x.c: In function 'inc': x.c:7: error: initializer element is not constant
xc:在函数“inc”中:xc:7:错误:初始值设定项不是常数
g++ is quite happy with it.
g++ 对此非常满意。
That is a difference between C and C++ that I was not aware of (but this wouldn't fit into 300 characters so I can't make it a comment, easily).
这是我不知道的 C 和 C++ 之间的区别(但这不适合 300 个字符,所以我不能轻易将其作为评论)。
@Eduardo asked one of the questions in the comments: "Why does C not allow this and C++ allow it?". Since the answer is more than 300 characters...
@Eduardo 在评论中提出了一个问题:“为什么 C 不允许这样做而 C++ 允许它?”。 由于答案超过300个字符......
As @litb said in the comments, in C you can only use constants for initializers of static variables. This is in part because the values are set before main() is called, and no user-defined functions are called before main() is called. C++, by contrast, allows global and static variables to be initialized by (user-defined) constructors before main() is called, so there's no reason not to allow other user-defined functions to be called too, so the initialization is reasonable. With C89, you are limited in the initializers you can use with automatic (local) variables; in C99, you can use pretty much any expression to initialize any local variable.
正如@litb 在评论中所说,在 C 中,您只能将常量用于静态变量的初始值设定项。这部分是因为值是在调用 main() 之前设置的,并且在调用 main() 之前没有调用用户定义的函数。相比之下,C++ 允许在调用 main() 之前由(用户定义的)构造函数初始化全局和静态变量,因此没有理由不允许其他用户定义的函数也被调用,因此初始化是合理的。使用 C89,您可以使用自动(局部)变量的初始化程序受到限制;在 C99 中,您几乎可以使用任何表达式来初始化任何局部变量。
回答by Jorge Ferreira
Access
is not static and therefore it must be created in every call.
Access
不是静态的,因此必须在每次调用中创建。
Consider simplifying the code to something like:
考虑将代码简化为:
static MyStruct Access = Implementation(this_b);
This ensures that the function will only be called the first time the method is run and that Access
will hold the value between calls.
这确保该函数只会在该方法第一次运行时被调用,并且Access
会在调用之间保存值。
回答by Michael
Access isn't static, therefore a new instance is created everytime the function is called. Only on the first time through do you actually assign any value to it; this value is lost as soon the function exits.
访问不是静态的,因此每次调用该函数时都会创建一个新实例。只有在第一次通过时,您才真正为其分配任何值;一旦函数退出,这个值就会丢失。
If you need Access to persist across calls to the function, make it static.
如果您需要 Access 在对函数的调用之间保持不变,请将其设为静态。