C++: 'cout << pointer << ++pointer' generates a compiler warning

独自空忆成欢 提交于 2019-12-30 18:27:04

问题


I have a C++ learning demo here:

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';

The compiler warnings:

Can anyone explain this to me? How to fix it?


回答1:


Since C++17 the code is correct.

Prior to C++17 the evaluation of operands of a << chain was unsequenced, so the code caused undefined behaviour.

The compiler warning suggests you are not compiling in C++17 mode. To fix it you could either:

  • Compile in C++17 mode, or
  • Separate the << chain into multiple cout << statements where there is not x and ++x within the same statement.

Note: As of now, all versions of g++ seem to be bugged and not implement these sequencing requirements correctly, see this thread for some more examples. The warnings can be seen as indicating the compiler bug; they are not just bogus warnings.




回答2:


According to C++ Standard Draft Paper N4762 (2018-07-07) on page 68 in section § 6.8.1/10

( or [intro.execution]/10 on eel.is website here )

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.


For statement

cout << c << '\t' << static_cast<void*>(cptr) << '\t' << static_cast<void*>(++cptr) << '\n';

that means c++ compiler can not guarantee that static_cast<void*>(cptr) will be evaluated before ++cptr on the right because they are all operands on the same statement.

So you can force their sequential order of execution simply by ordering them in ordered and separated statements.

For example :

cout << c << '\t' << static_cast<void*>(cptr) << '\t'; cout << static_cast<void*>(++cptr) << '\n';

[ compiler explorer ]


Update

As M.M's answer states that c++17 now guarantees operand evaluation sequence of <<

It turns out that GCC 8.1 doesn't warn, even with std=c++11, unless with -Wall and always warns with -Wall

While clang 6.0 warns "no matter what".

[ compiler explorer ]

So, as well as -std=c++17, you must also provide option -Wno-unsequenced to suppress it :

  • if you are on clang 6.0
  • if you are on gcc 8.1 with -Wall



回答3:


You re having undefined behavior in lines 18, 19, 20. Cause of the result of executing the line will be different depending on whether ptr or ++ptr is evaluated first.



来源:https://stackoverflow.com/questions/51550156/c-cout-pointer-pointer-generates-a-compiler-warning

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!