C 中的强制转换与隐式转换

Ait*_*bil 0 c casting implicit-conversion

我正在读一本关于 C 语言安全编码的书,我迷失的一点是强制转换和隐式转换之间的区别。请看一下下面的代码片段:

unsigned char a = 1;
unsigned char b = 2;

int c = b - a ;  //presumably implicit conversion
printf("%u" , (int)a - b );  // presumably casting
Run Code Online (Sandbox Code Playgroud)

(int) a-b 我在 Google 上找到了答案,但它们都与 C# 甚至 C++ 有关,但不是普通的 C ,所以有人可以解释一下这样做和分配给另一个这样的变量有什么区别吗int c = a - b

这里究竟发生了什么?提前致谢 。

Kei*_*son 5

转换可以是显式的,也可以是隐式的。显式转换由强制转换运算符指定。强制转换运算符是要转换的表达式前面的括号中的类型名称。(有时你会看到“隐式强制转换”这个短语。C 中没有这样的东西。)

对于给定的源和目标类型,隐式转换执行的操作与强制转换执行的操作相同。某些转换,特别是大多数指针转换,不会隐式执行,只能通过强制转换来完成。

隐式转换在 C 的许多上下文中完成。一些示例:

  • 在简单赋值中,右操作数会隐式转换为左操作数的类型。当将参数传递给函数、在初始化程序中以及执行语句时,也会发生同样的情况return
  • 当类似的操作+应用于不同算术类型的操作数时,它们会通过一组相当复杂的规则转换为通用类型。
  • int在许多上下文中,比隐式提升为intint的整数类型更窄unsigned

这不是一个完整的列表。

您的示例中有许多隐式转换:

unsigned char a = 1;
unsigned char b = 2;
Run Code Online (Sandbox Code Playgroud)

1并且2属于 类型intunsigned char它们由初始化器隐式转换。

int c = b - a ;  //presumably implicit conversion
Run Code Online (Sandbox Code Playgroud)

baint在执行减法之前提升为[但见下文]——不是因为结果将用于初始化对象int,而是因为这是提升规则指定的。减法的结果是 类型int,因此初始化不需要再进行转换。

printf("%u" , (int)a - b );  // presumably casting
Run Code Online (Sandbox Code Playgroud)

强制转换显式地将a a-b)从unsigned char转换为intb晋升为int. 该表达式(int)a - b的类型为int,并被传递给printf-- ,由于"%u"格式的原因,它需要一个类型为 的参数unsigned int。在某些情况下,您可以避免混合intunsigned int但由于减法的结果是-1,它超出了行为范围,unsigned int因此未定义。在我的系统上它打印4294967295. 使用 时%d,它将打印-1,这是表达式的实际值。unsigned int(如果你想要输出,你可以投射到4294967295。)

[脚注]

我说过 type 的值unsigned char被提升为int. 事实上,窄类型的整数表达式int会被转换为int if int可以表示窄类型的所有值,否则会被转换为unsigned int。在某些特殊系统上, 可能可以unsigned char表示比有符号更大的值int。在这样的系统上,unsigned char提升到unsigned int. 您不太可能遇到这样的系统。

  • 关于脚注,更可能的情况是 8/16 位计算机,其中“unsigned Short”(16 位)无法提升为“int”(16 位),因为“int”无法表示所有值。在这种特殊情况下,“unsigned Short”会转换为“unsigned int”。这种情况在任何使用“无符号短整型”的低端微控制器系统中都会遇到。 (2认同)