标题:关于未定义行为的警告
只看楼主
fantasyhpu
Rank: 2
等 级:论坛游民
帖 子:7
专家分:14
注 册:2019-6-9
结帖率:100%
已结贴  问题点数:20 回复次数:4 
关于未定义行为的警告
有一个简单的测试代码:
程序代码:
#include "stdio.h"

int main(void)
{

    int i,j;

    i=2;
    j=8;
    j=(i=6)+(j=3);//warning在这一行

    printf("%d %d",i,j);

    return 0;
}

编译时(gcc 8.1.0),出现一个未定义行为的警告:
warning: operation on 'j' may be undefined [-Wsequence-point]
对于出现warning的行:
j=(i=6)+(j=3);

我的理解是,先进行i=6和j=3的赋值运算,然后再计算j=6+3,即j=9。
这一过程很清晰,怎么编译器会抛出关于j的未定义行为warning呢?
搜索更多相关主题的帖子: 未定义 警告 warning int 出现 
2022-05-23 19:14
wp231957
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:神界
等 级:版主
威 望:422
帖 子:13681
专家分:53296
注 册:2012-10-18
得分:5 
回复 楼主 fantasyhpu
在相邻的两个序点中间,一个object的值可以并且只能被赋值一次
这种语句,说啥都要避免
在这个语句中,既要j等于这个又要j等于那个,编译器肯定懵逼

DO IT YOURSELF !
2022-05-23 23:14
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:507
帖 子:8890
专家分:53117
注 册:2011-1-18
得分:15 
wp231957说得对

先进行i=6和j=3的赋值运算,然后再计算j=6+3
“计算”是不可能的,顶多算“评估”,而且“评估”也是未指定顺序的;
j=(i=6)+(j=3) 有三部分,分别是 j、i=6、j=3,其中 j 作为左值先不谈,i=6 评估值是6,j=3评估值是3。注意,是“i=6”这个表达式的评估值为6,而不是说“i”等于6;j=3同样如此
那么在编译器眼中,j=(i=6)+(j=3) 就需要做 j=6+3、i=6、j=3 这三个操作,但这三个操作之间是未指定顺序的

要将 表达式评估副作用 分开,比如 i=123,它的表达式评估值是 123,也就是“i=123”这个表达式的值是 123,你可以写句 int result = (i=123) 试试,或 printf( "%d\n", i=123 ) 试试;
而“副作用”是指变量的值被修改了,比如“i=123”,它的评估值是123,它的副作用是i被修改为123。
但要注意的是,“副作用”只需要在下一个“序列点”之前发生就行了。举个例子
a = (b=3);
x = a + b;
其中 a = (b=3) 有两个副作用,分别是 a被赋值3、b被赋值3,但你没法确定哪一个先发生,但执行到 x = a + b; 时编译器保证“a被赋值3、b被赋值3”这两个副作用一定都已完成。
2022-05-24 09:01
fantasyhpu
Rank: 2
等 级:论坛游民
帖 子:7
专家分:14
注 册:2019-6-9
得分:0 
回复 3楼 rjsp
讲解的清楚明白,谢谢。
2022-05-24 11:21
fantasyhpu
Rank: 2
等 级:论坛游民
帖 子:7
专家分:14
注 册:2019-6-9
得分:0 
回复 2楼 wp231957
谢谢回复。
2022-05-24 11:22



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-509155-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018687 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved