我有以下程序
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int main(void) {
uint16_t o = 100;
uint32_t i1 = 30;
uint32_t i2 = 20;
o = (uint16_t) (o - (i1 - i2)); /*Case A*/
o -= (uint16_t) (i1 - i2); /*Case B*/
(void)o;
return 0;
}
案例A 编译时没有错误
案例B 会导致以下错误
[error: conversion to ‘uint16_t’ from ‘int’ may alter its value [-Werror=conversion]]
我正在使用的警告选项是:
-Werror -Werror=strict-prototypes -pedantic-errors -Wconversion -pedantic -Wall -Wextra -Wno-unused-function
我在Ubuntu 15.04 64位上使用GCC 4.9.2。
为什么我在案例B 中出现此错误,但在案例A 中却没有?
PS: 我使用clang编译器运行相同的示例,并且两种情况都编译得很好。
答案 0 :(得分:1)
您的案例B相当于:
o = o - (uint16_t) (i1 - i2); /*Case B*/
结果是int
可能不适合uint16_t
,因此,根据您的极端警告选项,它会产生警告(因此您会将警告视为错误,因此会出错)。
答案 1 :(得分:1)
整数促销是一件奇怪的事情。基本上,任何较小尺寸的所有整数值都会提升为int
,因此可以有效地操作它们,然后在存储时转换回较小的尺寸。这是C标准规定的。
所以,案例A真的是这样的:
o = (uint16_t) ((int)o - ((uint32_t)i1 - (uint32_t)i2));
(请注意,uint32_t
不适合int
,因此不需要宣传。)
而且,案例B看起来真的像这样:
o = (int)o - (int)(uint16_t) ((uint32_t)i1 - (uint32_t)i2);
主要区别在于案例A具有显式转换,而案例B具有隐式转换。
从GCC手册:
-Wconversion
警告可能会改变值的隐式转换。 ....
因此,只有案例B收到警告。