如果计算机是 "copying bits",为什么 signed int 会自动转换为 unsigned int?

Why is a signed int is auto-casted to an unsigned int if the computer is "copying bits"?

最近在学C,有不懂的地方

这里是例子,

int a = -1;
unsigned int b = a; 

在这个例子中,书上说,

  "a is auto-casted to 'unsigned int' and then assigned to 'unsigned int b'."

但是……为什么?我是说

'int a'是-1,所以它的位串应该是

1111 1111 1111 1111 1111 1111 1111 1111

从计算机的角度来看,它所要做的就是只是将位复制到 unsigned int b

无需将 'signed int' 转换为 'unsigned int' !

我不明白,为什么他们在复制位之前自动将 'signed int' 转换为 'unsigned int'?

C 按值给变量赋值,而不是按表示。 -1 显然不能用无符号类型表示,因此必须进行转换。这里的规则(从有符号类型到无符号类型)是一个转换"modulo",因此-1最终是无符号类型的最大值。

如果你想 "assign" 通过表示,你将不得不使用复制函数,例如 memcpy,但请注意,如果原始位模式,这可能会导致未定义的行为目标类型不支持。

此外,对于词汇,在 C 中我们说的是 "conversions"。您在这里拥有的是隐式转换。显式转换也叫"casts".

您的书似乎并没有意识到所有这些,并且使用了奇怪的词汇。如果你给自己买一个新的更好的可能会更好。

嗯...当你用signed int值初始化一个unsigned int对象时,肯定需要将unsigned int转换为signed int。这正是您通过在初始化中混合这两种不同类型而要求语言执行的操作。当您使用不同类型 U 的值初始化类型 T 的对象时,类型 U 必须隐式 转换 为类型 T. (或者必须报告错误,如果没有适当的转换。)没有办法绕过它。除了转换之外,无法 "mate" 两种不同的类型。

此外,没有 "bit copying" 这样的东西。我不知道为什么你的书决定在这种情况下发明这样的概念。当一个 singed int 值转换为 unsigned int 类型时,有符号值根据模运算规则进行转换。这就是你的情况。在 2 的补码平台上,转换是概念性的,这意味着值的位表示不会改变(这显然是 "bit copying" 的意思)。

太多程序员接受的教育是他们编写程序时假设所有负数都表示为 2 的补码,并假设 signed/unsigned 转换是按位复制。

然而,语言无意强制每个 computer/compiler 以这种方式完全表示负数,尽管它很流行。

C 放宽了负数表示的要求以提供更大的实现灵活性,但同时使 "conventional" 2's-complement-bitwise-copy 类型转换成为标准的一部分,以便大多数时候,那些错误的假设不会造成问题。