我在这里有一个C ++学习演示:
char c = 'M';
short s = 10;
long l = 1002;
char * cptr = &c;
short * sptr = &s;
long * lptr = &l;
cout << "cptr:\t" << static_cast<void*>(cptr) << '\n';
cout << "cptr++:\t" << static_cast<void*>(++cptr) << '\n';
cout << "sptr:\t" << sptr << '\n';
cout << "sptr++:\t" << ++sptr << '\n';
cout << "lptr:\t" << lptr << '\n';
cout << "lptr++:\t" << ++lptr << '\n';
cout << c << '\t' << static_cast<void*>(cptr) << '\t' << static_cast<void*>(++cptr) << '\n';
cout << s << '\t' << sptr << '\t' << ++sptr << '\n';
cout<< l << '\t' << lptr << '\t'<< ++lptr << '\n';
编译器警告:
有人可以向我解释吗?如何解决?
答案 0 :(得分:9)
Since C++17 the code is correct。
Prior to C++17对<<
链的操作数的求值是未排序的,因此代码导致未定义的行为。
编译器警告提示您未在C ++ 17模式下进行编译。要解决此问题,您可以:
<<
链分成多个cout <<
语句,其中同一语句中没有x
和++x
。注意:到目前为止,所有g ++版本似乎都存在漏洞,无法正确实现这些排序要求,有关更多示例,请参见this thread。这些警告可以视为指示编译器错误;它们不只是虚假的警告。
答案 1 :(得分:2)
根据C ++标准草案N4762(2018-07-07)第68页§6.8.1 / 10
(或 eel.is 网站here上的 [intro.execution] / 10 )
除非另有说明,否则对单个运算符的操作数和各个表达式的子表达式的求值是无序列的。
要声明
cout << c << '\t' << static_cast<void*>(cptr) << '\t' << static_cast<void*>(++cptr) << '\n';
这意味着c ++编译器不能不能保证static_cast<void*>(cptr)
将在右边的++cptr
之前进行求值,因为它们都是相同的相同的操作数声明。
因此,您可以简单地通过按有序和分隔的语句对它们进行排序来强制执行它们的顺序执行。
例如:
cout << c << '\t' << static_cast<void*>(cptr) << '\t'; cout << static_cast<void*>(++cptr) << '\n';
M.M的回答指出,c ++ 17现在可以保证<<
的操作数求值顺序
事实证明,即使使用std=c++11
也不会警告GCC 8.1,除非使用-Wall
并始终使用-Wall
警告
当clang 6.0警告“无论如何”时。
因此,与-std=c++17
一样,您还必须还提供选项-Wno-unsequenced
来禁止它:
-Wall
在gcc 8.1上答案 2 :(得分:1)
您在18, 19, 20
行中有未定义的行为。根据首先评估ptr
还是++ptr
,执行该行的结果的原因会有所不同。