C++ 将无符号的负数分配给有符号,可以吗?

C++ 将无符号的负数分配给有符号,可以吗?,c++,type-conversion,unsigned,C++,Type Conversion,Unsigned,当我运行此命令时: int main() { unsigned a = 5; std::cout << -a << std::endl; int b = -a; std::cout << b << std::endl; return 0; } 它似乎有效,我可以取无符号的负数,并将其分配给int,但这真的总是可以吗?为什么? 当我尝试一些在我看来类似的情况时: int c = 1; int d = 3;

当我运行此命令时:

int main() {
    unsigned a = 5;
    std::cout << -a << std::endl;
    int b = -a; 
    std::cout << b << std::endl;
    return 0;
}
它似乎有效,我可以取
无符号
的负数,并将其分配给
int
,但这真的总是可以吗?为什么?

当我尝试一些在我看来类似的情况时:

int c = 1;
int d = 3;
double x = c/d;
std::cout << x << std::endl;
intc=1;
int d=3;
双x=c/d;

std::cout只要您的目标体系结构使用两位互补算法,并且将
int
视为32位,就可以了。否则,您的第一个程序将得到不同的结果。

。你有未定义的行为可能性

下面是一个计数器示例,当将一个求反的
无符号int
赋值给一个
int
时,会生成UB:

unsigned u = (unsigned)std::numeric_limits<int>::max() - 1;
std::cout << "max int" << std::numeric_limits<int>::max() << '\n';
std::cout << "as unsigned - 1" << u << '\n';
std::cout << "negated:" << -u << '\n';
std::cout << std::boolalpha << ( std::numeric_limits<int>::max() < -u ) << '\n';
int s = -u;
std::cout << s << '\n';
请注意,即使您知道
-a
将是一个可以用
int
表示的值,编译器仍然会警告您

签名溢出时:

关于C和C++中定义良好的无符号溢出:

关于隐式转换:


我“几乎”肯定C++继承了C转换的类型转换,添加C标记和搜索C区域。读这个,它只是一个二进制魔法。同一个二进制表示法被不同地解释为有符号或无符号值。另请参见这里@JonnyHenly的“always OK”,我的意思是我不确定我是否遇到了一个幸运的例子,因为实际上我并不认为这会起作用。第二个例子是因为我能解释这种行为的唯一方法是,在assignment@cmaster如果指定的值大于
int
所表示的值,则触发UB。即使
无符号的
上的原始操作定义得很好。@cmaster我还没有看到。C++ 14仍然有[ExpR]/4,如果在表达式的计算中,结果在数学上没有定义,或者在其类型的可表示值范围内,行为是未定义的。@ CMASTER,我添加了一个最近的C++标准的引用,它与你所说的相矛盾。记住这个问题是C++,C++中可能是正确的,好吧,也许你对C++是正确的。删除了我的东西。
unsigned u = (unsigned)std::numeric_limits<int>::max() - 1;
std::cout << "max int" << std::numeric_limits<int>::max() << '\n';
std::cout << "as unsigned - 1" << u << '\n';
std::cout << "negated:" << -u << '\n';
std::cout << std::boolalpha << ( std::numeric_limits<int>::max() < -u ) << '\n';
int s = -u;
std::cout << s << '\n';
unsigned a = 5;
std::cout << -a << '\n';
int b{ -a }; // compiler detects narrowing conversions, warning/error
std::cout << b << '\n';
return 0;