Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么编译器允许自己初始化变量?_C - Fatal编程技术网

C 为什么编译器允许自己初始化变量?

C 为什么编译器允许自己初始化变量?,c,C,我终于找到了一个打字错误,它类似于下面的代码。 但是编译器不应该检测到这一点吗(默认选项) #包括 int main() { int c=c; 返回printf(“%d\n”,c); } $gcc—版本 gcc(Ubuntu 4.4.3-4ubuntu5.1)4.4.3 我不明白为什么它不能编译。定义发生在初始化之前。当然,这个初始化是没有意义的,但是,从编译器的角度来看,没有理由不起作用 C没有像C这样的现代语言那样的保护类型。C#编译器会给出一个错误,即您使用的是未赋值变量。C不在乎。它不会

我终于找到了一个打字错误,它类似于下面的代码。 但是编译器不应该检测到这一点吗(默认选项)

#包括
int main()
{
int c=c;
返回printf(“%d\n”,c);
}
$gcc—版本
gcc(Ubuntu 4.4.3-4ubuntu5.1)4.4.3

我不明白为什么它不能编译。定义发生在初始化之前。当然,这个初始化是没有意义的,但是,从编译器的角度来看,没有理由不起作用


C没有像C这样的现代语言那样的保护类型。C#编译器会给出一个错误,即您使用的是未赋值变量。C不在乎。它不会保护您自己。

在自己的初始值设定项中使用变量是完全合法的。考虑链接列表:

#include <stdio.h>
struct node { struct node *prev, *next; int value; };
int main() {
    struct node l[] = {{0, l + 1, 42}, {l, l + 2, 5}, {l, 0, 99}};
    for (struct node *n = l; n; n = n->next)
        printf("%d\n", n->value);
    return 0;
}
#包括
结构节点{struct node*prev,*next;int-value;};
int main(){
结构节点l[]={{0,l+1,42},{1,l+2,5},{1,0,99};
对于(结构节点*n=l;n;n=n->next)
printf(“%d\n”,n->value);
返回0;
}

通常,在未初始化的情况下使用值时进行诊断是一个困难的问题;尽管某些编译器在某些情况下可以检测到它,但要求它发生是没有意义的。

您在初始化时调用未定义的行为;编译器不需要诊断问题,也不需要定义遇到问题时它会做什么。我敢打赌,当您打开警告(-GCC中的Wall)时,它会在您执行此操作时向您发出警告。尽量不要忽略警告;-)我使用GCC4.7.1和编译器选项:
GCC-O3-g-std=c99-Wall-Wextra-Wmissing原型-Wstrict原型-Wold样式定义-cx.c
,抱怨的是“不是原型”和“旧式函数定义”,而不是变量初始化。OTOH,
clang
已诊断:
x.c:5:13:警告:变量“c”在其自身初始化中使用时未初始化[-Wuninitialized]
(但将
-Wuninitialized
添加到GCC选项并不会添加到消息中-
clang
在此处具有更好的诊断功能).gcc有一个
-Winit self
标志。@nothrow给我你的鞋子,
-Wall-Wextra
在gcc 4.9.3中不包括
-Winit self
。这个初始化,而不是赋值。另外,能够引用变量进行初始化也很有用,因为你可以获取它的地址,如
int x=initialize\u和\u register(&x)中所示
。(这种调用通常打包在宏中。)@user4815162342 true,这显然是有道理的。我应该选择更好的词:(你的词很好(除了初始化和赋值之间的区别),我只是提供了一个进一步改进答案的建议。你的答案并没有明确说明在表达式中使用
x
实际上是有用的,所以这不仅仅是关于C不能保护你自己。如果你想在答案中添加这些信息,这就是“编辑”按钮的作用是::)这就是C“警告”存在的原因:它们不会触发错误,只是警告程序员可疑的模式。未定义的行为如何合法?这不是用本身初始化变量,而是指向自身的指针,因为
l
会衰减为指针
&[0]
在这种情况下。@在这种特殊情况下(数组到指针衰减),是的。在大多数情况下不会。
#include <stdio.h>
struct node { struct node *prev, *next; int value; };
int main() {
    struct node l[] = {{0, l + 1, 42}, {l, l + 2, 5}, {l, 0, 99}};
    for (struct node *n = l; n; n = n->next)
        printf("%d\n", n->value);
    return 0;
}