我有一个非常简单的逻辑算法代码,涉及从std::atomic_bool
返回的值。
#include <iostream>
#include <atomic>
int main() {
uint16_t v1 = 0x1122;
uint16_t v2 = 0xaaff;
std::atomic_bool flag1(false);
uint16_t r1 = v1 | v2;
std::cout << std::hex << r1 << std::endl;
uint16_t r2 = static_cast<uint16_t>(flag1.load()) | static_cast<uint16_t>(0xaaff);
std::cout << std::hex << r2 << std::endl;
std::cout << __VERSION__ << std::endl;
}
代码示例为here。编译行:g++ -std=c++17 -O3 -Wall -pedantic -Wconversion -pthread main.cpp && ./a.out
。
基于STD API,load()
应返回存储在原子中的带下划线的类型。因此flag1.load()
应该返回bool
。但是,编译器会发出警告,要求它将int
转换为uint16_t
:
main.cpp:13:55: warning: conversion from 'int' to 'uint16_t' {aka 'short unsigned int'} may change value [-Wconversion]
uint16_t r2 = static_cast<uint16_t>(flag1.load()) | static_cast<uint16_t>(0xaaff);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这种转换到底在哪里? |
的双方都转换为uint16_t
。为什么还在打印警告?
答案 0 :(得分:1)
Usual arithmetic conversions(在ISO标准的第5节中指定)定义大多数或所有算术和二元运算符的任何操作数在操作本身之前进行整数提升。
这意味着两个uint16_t
个操作数首先会提升为int
以计算按位|
,然后截断回uint16_t
以存储在r2
中。
确实警告的含义是:int
隐含地截断uint16_t
。
这些转换还定义bool
将始终评估为1或0,因此第一个转换是无用的,但由于第二个操作数将被提升为int
,因此第二个转换也是没用,你可以选择
uint16_t r2 = flag.load() | 0xaaff;
并且可能通过明确地转换为更窄的类型来使警告静音,这使您意识到这种情况正在发生:
uint16_t r2 = static_cast<uint16_t>(flag.load() | 0xaaff);