在同一表达式中解引用并递增指针p是否会导致未定义行为?
表达式中指针读写的未定义行为疑问
在Bjarne Stroustrup所著《C++编程原理与实践》第8.6.1章中提到:子表达式的求值顺序由优化器导向的规则决定,需遵循规则:若在表达式中修改变量值,请勿在同一表达式中对其进行两次读写,并列举了如下未定义行为示例:
v[i] = ++i; // don’t: undefined order of evaluation v[++i] = i; // don’t: undefined order of evaluation int x = ++i + ++i; // don’t: undefined order of evaluation cout << ++i << ' ' << i << '\n'; // don’t: undefined order of evaluation f(++i,++i); // don’t: undefined order of evaluation此类代码因编译器、平台或优化设置不同可能产生不同结果,且部分编译器不会发出警告。
之后发现一段用于输出对象字节表示的代码:
template <typename T> void print_bytes(const T& input, std::ostream& os = std::cout) { const uint8_t* p = reinterpret_cast<const uint8_t*>(&input); os << std::hex << std::showbase; os << "["; for (unsigned int i = 0; i < sizeof(T); ++i) { os << std::setw(5) << static_cast<int>(*(p++)) << " "; } os << "]" << std::endl; os << std::dec << std::noshowbase; }
其中os << std::setw(5) << static_cast<int>(*(p++)) << " ";一行中,指针p在同一表达式中被解引用并递增,请问该写法是否会因编译器、平台不同产生行为差异,是否属于未定义行为?
结论:这段代码不属于未定义行为,不会因编译器/平台差异产生行为差异
原因如下:
- 链式
operator<<是独立函数调用:C++中,a << b << c的本质是operator<<(operator<<(a, b), c),每个operator<<调用都是一个独立操作,前一个调用的所有副作用(比如变量修改)都会在后续调用开始前完全完成。 - 后置递增运算符语义明确:
*(p++)的行为固定——先解引用当前指针p指向的值,再将p自增1,这个操作的求值顺序和副作用没有歧义。 - 对比书中的未定义行为:书中的例子都是在同一个运算符的操作数之间(比如
++i + ++i)或同一函数的参数列表中(比如f(++i, ++i))存在无明确顺序的读写操作,而这段代码的链式输出是多个有序的函数调用,不存在这种无序冲突。
内容的提问来源于stack exchange,提问作者a_floating_point
相关产品推荐
相关产品推荐

