#include <stdio.h>
int main(){
int i = 5;
{
int i = i;
printf("i=%d\n",i);
}
printf("i=%d\n",i);
}
我的想法是这样的,赋值运算符不是从右向左结合么,所以 i = i 时,右侧的 i 还是父块中 i ,左边的 i 被赋值,应该也等于 5 ,但此时已经是子块中的本地变量了。
不过觉得奇怪的是,输出结果是这样的:
i = 1
i = 5
我完全不理解这个 i=1 是怎么来的?我反复尝试了几次之后都是 i=1 ,我个人觉得就算我想的不对,那也应该报错或者是被赋一个乱七八糟的随机数,但是这个 1 。。。我是真的没想通。。
谢谢!
1
corvofeng 2017-02-04 15:50:47 +08:00 via Android 1
试验了下 gcc6.3 输出是 0 , 5
clang3.9 输出是 4195312 , 5 , 可能这种赋值没法预测结果吧 |
2
kokutou 2017-02-04 15:53:47 +08:00 via Android
int j = i;
这样比较符合你的预期。。。 |
3
yuchting 2017-02-04 15:56:36 +08:00 via Android
这个真的和编译器有关,按照我学习的理论应该是 5 , 5 。这个属于调戏编译器的代码,现实开发中需要极度避免。
|
4
Newyorkcity OP |
5
coderluan 2017-02-04 16:02:22 +08:00
|
6
nodeath 2017-02-04 16:39:10 +08:00
应该理解为先定义在赋值啊,你赋值的那个 i 已经是局域变量了。
|
7
introom 2017-02-04 16:47:16 +08:00 via Android 1
@coderluan 这不是未定义行为。。。。
楼主,你写完 int i 的时候, i 就在作用域可见,所以右边 i 指代左边没有初始化的 i. 这种基础语法认知应当所有主流编译器都会报 warning 的。 具体名称,在 spec 的前面就有,我在手机,打字已然很累,所以就不给具体链接了。 最后,你的问题很好,因为是个很基础的问题。 |
8
coderluan 2017-02-04 17:44:24 +08:00 2
@introom
warning 是编译器定义的, undefined behavior 是标准定义的,不能说有 warning 就不能叫 undefined behavior 了吧。 按标准来说,使用了 uninitialized 变量叫做 undefined behavior 了。 http://stackoverflow.com/questions/11962457/why-is-using-an-uninitialized-variable-undefined-behavior-in-c |
9
introom 2017-02-04 18:46:46 +08:00 1
@coderluan 大哥你说的对,我看了一下 http://eel.is/c++draft/dcl.init#12 ,除了 unsigned char 以外,直接访问都是 undefined behavior, 我回复你的时候,觉得那是 unspecified behavior, 和有没有 warning 没关系。
安腾处理器蛮有意思的, NaT bit,直接访问 trap 。。。。学习了。 |
10
Newyorkcity OP |
11
htfy96 2017-02-04 21:15:21 +08:00
话说最近 C++委员会的 Scott Meyer 好像发推说要在下个 C++版本中让 int x = x 这种语法直接 ill-formed
|
14
visionsmile 2017-02-18 13:48:15 +08:00 1
@corvofeng
@Newyorkcity @coderluan @introom @htfy96 题主这个是 Point of declaration 的问题,在 C++标准中是有描述的: The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [ Example: unsigned char x = 12; { unsigned char x = x; } Here the second x is initialized with its own (indeterminate) value. — end example ] |
15
coderluan 2017-02-18 14:11:06 +08:00
|
16
visionsmile 2017-02-18 14:59:19 +08:00
@coderluan 这个不叫未定义行为啊,应该叫这个 object 具有不确定的值(indeterminate value)
C 语言标准里面没有直接提到这种写法,但是也可以间接地推导出来: >If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope. 以及: >If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. 未定义行为是标准没有描述它会产生什么样的行为(行为不可预测),但是就这个问题而言,标准也是规定了它具有不确定的值(也就是描述了它会产生不确定值的行为)..所以就不是未定义行为.... |
17
coderluan 2017-02-18 15:16:48 +08:00
@visionsmile 懂了,谢谢
|
18
Newyorkcity OP @visionsmile 请问这些资料在哪里可以看到?谢谢
|
19
visionsmile 2017-02-19 10:45:29 +08:00
@Newyorkcity 我整理了一个 C/C++相关的文档列表,可以在这里下载: [doc.imzlp.me]( http://doc.imzlp.me/) ,我上面提到的 C++标准是 ISO/IEC 14882:2014 和 C 标准 ISO/IEC 9899:2011.
|