为什么从无符号短整型到有符号字符没有发生隐式类型转换?

huangapple go评论86阅读模式
英文:

Why isn’t implicit type conversion happening from unsigned short int to signed char?

问题

Output: a is small

在代码2中,unsigned short int(第4行)大于signed char(第3行),为什么不发生隐式转换?

或者

为什么unsigned short intsigned char的隐式转换没有发生?

请注意,我已经按照您的要求,只返回翻译好的部分。

英文:

code 1:

#include <stdio.h>

int main()
{
    short int a = -1; // ----> Line 1
    unsigned int b = 122; // ----> Line 2
    
    if (a > b)
        printf("a is big");
    else
        printf("a is small");

    return 0;
}

Output: a is big

Since here the Line 1 is implicitly converted to Line 2, ie: signed short int to unsigned int.

similarly

code 2:

#include <stdio.h>

int main()
{
    char a = -1; // ---> Line 3
    unsigned short int b = 122; // ---> Line 4
    
    if (a > b)
        printf("a is big");
    else
        printf("a is small");

    return 0;
}

Output: a is small

Here in code 2, since unsigned short int (Line 4) is greater than signed char (Line 3), why is the implicit conversion not happening?

or

Why doesn't the implicit conversion for unsigned short int and signed char take place?

答案1

得分: 2

This little riddle hides a difficult problem: integer promotions may behave differently on different systems, depending on the size of types char, short, and int.

When an operation is evaluated between types that have a rank lesser or equal to that of int, integer promotions are performed and the operation is evaluated on the resulting type, int or unsigned int depending on the original types.

If both types are smaller (have fewer value bits) than int, they are promoted to int, which preserves the value. If one or both have the same number of value bits as unsigned int, they are both promoted to unsigned int, which changes negative values to large positive ones.

In addition to this difficulty, you are storing the value -1 to a variable of type char. Depending on the signedness of type char, the value -1 may be converted to the positive value UCHAR_MAX. This is the case if type char is unsigned.

Let's investigate your examples:

code 1:

short int a = -1; // Line 1
unsigned int b = 122; // Line 2

short int a is promoted to unsigned int, the type of b, and the value -1 changes to UINT_MAX, which is much larger than 122, hence the comparison is true, a is big. This behavior does not depend on the architecture.

code 2:

char a = -1; // Line 3
unsigned short int b = 122; // Line 4

  • if char is signed, a has the value -1, but if char is unsigned, a would have the value UCHAR_MAX, which is 255 on architectures with 8-bit bytes.

  • if type unsigned short int has the same size as unsigned int (16-bit architectures), both values are promoted to unsigned int (-1 becomes UINT_MAX) and the comparison is either UINT_MAX > 122 or 255 > 122, which is true in both cases.

  • if type unsigned short int is smaller than int, both values are promoted to int and the comparison is either -1 > 122 or 255 > 122, which depends on the signedness of type char.

Your system outputs a is small, which means char is signed, and short has fewer bits than int, so the comparison is -1 > 122, which is false.

英文:

This little riddle hides a difficult problem: integer promotions may behave differently on different systems, depending on the size of types char, short and int.

When an operation is evaluated between types that have a rank lesser or equal to that of int, integer promotions are performed and the operation is evaluated on the resulting type, int or unsigned int depending on the original types.

If both types are smaller (have fewer value bits) than int, they are promoted to int, which preserves the value. If one or both have the same number of value bits as unsigned int, they are both promoted to unsigned int, which changes negative values to large positive ones.

In addition to this difficulty, you are storing the value -1 to a variable of type char. Depending on the signedness of type char, the value -1 may be converted to the positive value UCHAR_MAX. This is the case if type char is unsigned.

Let's investigate your examples:

code 1:

short int a = -1; // ----> Line 1
unsigned int b = 122; // ----> Line 2

short int a is promoted to unsigned int, the type of b and the value -1 changes to UINT_MAX, which is much larger than 122, hence the comparison is true, a is big. This behavior does not depend on the architecture.

code 2:

char a = -1; // ---> Line 3
unsigned short int b = 122; // ---> Line 4
  • if char is signed, a has the value -1, but if char is unsigned, a would have the value UCHAR_MAX, which is 255 on architectures with 8-bit bytes.

  • if type unsigned short int has the same size as unsigned int (16-bit architectures), both values are promoted to unsigned int (-1 becomes UINT_MAX) and the comparison is either UINT_MAX > 122 or 255 > 122, which is true in both cases.

  • if type unsigned short int is smaller than int, both values are promoted to int and the comparison is either -1 > 122 or 255 > 122, which depends on the signedness of type char.

Your system outputs a is small, which means char is signed and short has fewer bits than int, so the comparison is -1 > 122, which is false.

答案2

得分: 1

charsigned charunsigned charshortunsigned short 从不被视为整数提升的结果类型。

整数提升起源于早期的C开发,那时算术运算主要使用本地处理器寄存器以其普通宽度进行,而charshort是用于存储数据的类型。int类型被用作处理器上的“自然”类型,与其寄存器匹配。因此,charshort数据被加载到处理器寄存器中,然后使用实际上执行int算术的指令进行操作。当前的标准C规则反映了这一历史;整数提升将整数类型提升至至少intunsigned int

在您的C实现中,unsigned short intint窄,因此它被提升为intchar也是如此。因此,char值-1被提升为int,产生了一个值为-1的int值,而unsigned short int值为122被提升为int,产生了一个值为122的int值,然后这些值被比较。然后-1不大于122,所以a > b评估为假。

通常的算术转换的具体规则如下:

  • 如果其中一个操作数(或者如果是复数,则是其相应的实际类型)是long double,则将另一个操作数转换为long double

  • 否则,如果其中一个操作数(或者如果是复数,则是其相应的实际类型)是double,则将另一个操作数转换为double

  • 否则,如果其中一个操作数(或者如果是复数,则是其相应的实际类型)是float,则将另一个操作数转换为float

  • 否则,整数提升将在两个操作数上执行:具有整数转换等级低于int的类型的值,如果int可以表示源类型的所有值(例如,如果unsigned short的宽度与int相同,则具有int无法表示的一些值),否则转换为unsigned int。(具有较高等级的类型不会转换。)具有_Boolintunsigned int位字段类型的值也以这种方式转换。

  • 如果两个结果操作数具有相同的类型,则不执行进一步的转换。

  • 否则,如果两者具有有符号类型或都具有无符号类型,则将具有较低等级的操作数转换为另一种类型。

  • 否则,如果无符号类型的等级至少等于有符号类型的等级,则将有符号类型转换为无符号类型。

  • 否则,如果有符号类型可以表示无符号类型的所有值,则将无符号类型转换为有符号类型。

  • 否则,两个操作数都将转换为与有符号类型对应的无符号类型。(例如,如果操作数是unsigned shortint,它们具有相同的宽度,它们将被转换为unsigned int。)

英文:

char, signed char, unsigned char, short, and unsigned short are never considered as result types of the integer promotions.

The integer promotions originated in early C development where arithmetic was largely done using the native processor registers in their ordinary widths, and char and short were types used for storing data. The int type was used as the “natural” type on the processor, matching its registers. So char and short data was loaded into processor registers and then operated on with, in effect, instructions that performed int arithmetic. The current rules of standard C reflect this history; the integer promotions bring integer types up to at least int or unsigned int.

In your C implementation, unsigned short int is narrower than int, so it is promoted to int. So is char. Thus the char value −1 is promoted to int, yielding an int value of −1, and the unsigned short int value of 122 is promoted to int, yielding an int value of 122, and these are compared. Then −1 is not greater than 122, so a > b evaluates as false.

The specific rules for the usual arithmetic conversions are:

  • If either operand (or, if complex, its corresponding real type) is long double, the other operand is converted to long double.

  • Otherwise, if either operand (or, if complex, its corresponding real type) is double, the other operand is converted to double.

  • Otherwise, if either operand (or, if complex, its corresponding real type) is float, the other operand is converted to float.

  • Otherwise, the integer promotions are performed on both operands: A value with a type with integer conversion rank less than int is converted to int if int can represent all values of the source type (for example, if unsigned short is the same width as int, it has some values that int cannot represent) or to unsigned int otherwise. (Values with a type with greater rank are not converted.) Values with bit-field types of _Bool, int or unsigned int are also converted in this way.

  • If both resulting operands have the same type, no further conversion is performed.

  • Otherwise, if both have signed type or both have unsigned type, the operand with lower rank is converted to the other type.

  • Otherwise, if rank of the unsigned type is at least the rank of the signed type, the signed type is converted to the unsigned type.

  • Otherwise, if the signed type can represent all the values of the unsigned type, the unsigned type is converted to the signed type.

  • Otherwise, both operands are converted to the unsigned type corresponding to the signed type. (For example, if the operands are unsigned short and int, and those have the same width, they will be converted to unsigned int.)

huangapple
  • 本文由 发表于 2023年5月29日 23:24:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358529.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定