我猜答案是“不”,但从编译器的角度来看,我不明白为什么。
我制作了一个非常简单的代码,它使得编译器诊断非常糟糕(包括clang和gcc),但我想确认在报告错误诊断之前代码没有格式化。我应该指出,这些不是编译器错误,输出在所有情况下都是正确的,但我对这些警告有疑问。
请考虑以下代码:
#include <iostream>
int main(){
int b,a;
b = 3;
b == 3 ? a = 1 : b = 2;
b == 2 ? a = 2 : b = 1;
a = a;
std::cerr << a << std::endl;
}
a
的分配是重言式,意味着a
将在两个三元语句之后初始化,而不管b
。 GCC对此代码非常满意。 Clang更聪明,发现了一些愚蠢的东西(warning: explicitly assigning a variable of type 'int' to itself [-Wself-assign]
),但没什么大不了的。
现在同样的事情(至少在语义上),但语法更短:
#include <iostream>
int main(){
int b,a = (b=3,
b == 3 ? a = 1 : b = 2,
b == 2 ? a = 2 : b = 1,
a);
std::cerr << a << std::endl;
}
现在编译器给了我完全不同的警告。 Clang不再报告任何奇怪的事情(由于括号优先,这可能是正确的)。 gcc有点吓人,并说:
test.cpp: In function ‘int main()’:
test.cpp:7:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
但这是真的吗?这个序列点警告给了我一个暗示,在实践中不会以相同的方式处理昏迷分离的语句,但我不知道它们是否应该。
它变得怪异,将代码更改为:
#include <iostream>
int main(){
int b,a = (b=3,
b == 3 ? a = 1 : b = 2,
b == 2 ? a = 2 : b = 1,
a+0); // <- i just changed this line
std::cerr << a << std::endl;
}
然后突然发现clang意识到a
可能有些可疑的东西:
test.cpp:7:14: warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]
a+0);
^
但之前a
没有问题......由于某些原因,clang在这种情况下无法发现同义词。同样,它可能只是因为那些不再是完整的陈述。
问题是:
a
在最后一种情况下可能未初始化? (那么它应该对前一种情况有相同的诊断)编辑和评论
答案 0 :(得分:1)
5个表达
10在某些情况下,表达式仅出现其副作用。这种表达式称为丢弃值 表达。评估表达式并丢弃其值
5.18逗号运算符[expr.comma]
用逗号分隔的一对表达式从左到右进行评估; 左表达式是一个废弃值表达式(第5条).83每个 值计算和与左表达式相关的副作用 在每个值计算和副作用相关之前进行排序 用正确的表达方式。结果的类型和值是 右操作数的类型和值;结果具有相同的值 category作为右操作数,如果是右操作数则是一个位字段 是一个glvalue和一个位域。
我觉得你的陈述没有错。
仔细观察g ++警告,可能未定义,这告诉我解析器不够聪明,无法确保a=1
被评估。