C 我什么时候可以不使用signed声明int?
在C中,像-1这样的有符号整数应该用关键字C 我什么时候可以不使用signed声明int?,c,types,printf,undefined-behavior,C,Types,Printf,Undefined Behavior,在C中,像-1这样的有符号整数应该用关键字signed声明,如下所示: signed int i = -1; 然而,我试过这样做: signed int i = -2; unsigned int i = -2; int i = -2; 所有3个案例都打印出-2个printf(“%d”,i)。为什么?整数变量的打印方式取决于传递给printf的格式字符串: 如果使用%d,则将其打印为带符号整数 如果使用%u,则将其打印为无符号整数 自从您确认您正在使用以下方式打印: printf("%d",
signed
声明,如下所示:
signed int i = -1;
然而,我试过这样做:
signed int i = -2;
unsigned int i = -2;
int i = -2;
所有3个案例都打印出-2个
printf(“%d”,i)代码>。为什么?整数变量的打印方式取决于传递给printf
的格式字符串:
- 如果使用
%d
,则将其打印为带符号整数
- 如果使用
%u
,则将其打印为无符号整数
自从您确认您正在使用以下方式打印:
printf("%d", i);
这是在未签名的情况下。fprintf函数的7.19.6.1
一节中介绍了这一点,该函数还包括格式说明符的printf
,第9段中说明:
如果转换规范无效,则行为未定义。248)[…]
第3.4.3节未定义行为中定义的标准如下:
使用不可移植或错误的程序结构或错误的数据时的行为,
本国际标准对其无任何要求
并进一步指出:
可能的未定义行为包括:完全忽略情况并产生不可预测的结果,在翻译或程序执行过程中以环境特有的方式(无论是否发出诊断消息)进行行为,以及终止翻译或执行(发出诊断信息)
最后,我们可以看到int与signed int相同。我们可以通过查看第2段中的6.7.2
类型说明符一节来了解这一点,它将int分组如下:
int,signed,或signed int
后来第5段说:
每个逗号分隔的集合指定相同的类型,但位字段[…]除外
printf
无法知道传递给它的是什么。C编译器在传递参数时执行默认类型提升,然后函数本身根据传递的格式说明符重新解释值,因为它没有关于传递的值类型的其他信息
当您在%d
位置将无符号int
传递给printf
时,这是未定义的行为。您的程序不正确,它可以打印任何内容
在用2的补码表示法表示负数的硬件上,可能会得到与开始时相同的数字。然而,这不是一个普遍的规则。您有两件事要做:
unsigned int i = -2; // i actually holds 4294967294
printf("%d", i); // printf casts i back to an int which is -2 hence the same output
有符号和无符号是解释相同64位(或32位或其他)的不同方式
Printf是一个可变函数,它接受不同类型的参数
将有符号值(-2)传递给无符号变量,然后要求printf将其解释为有符号
记住,“有符号”和“无符号”与数字的运算方式有关。
printf系列接受基于格式指示符传入的任何类型的内部强制转换。(这是接受多种类型参数的可变函数的性质。它们不能使用传统的类型安全机制)
这一切都很好,但并非所有的事情都是一样的
加法和减法在大多数体系结构上都是一样的(只要你不是在一些不使用2的补码表示负数的古怪体系结构上)
乘法和除法也可以起同样的作用。
不平等性比较是最难知道它们如何工作的,我已经多次在有符号和无符号之间进行比较,我认为这是可以的,因为它们在小符号范围内
这就是“未定义”的含义。行为由编译器和硬件实现者决定,不能依赖于不同体系结构之间的行为相同,甚至不能依赖于同一体系结构上的行为随时间的推移而相同。如何将它们打印出来?printf(“%d”)
使用无符号将是未定义的行为。为什么您认为有符号整数需要有符号
?我使用了printf(“%d”,I);显示如何打印它。如果是printf(“%d”,I)
然后注意%d
是有符号整数的格式说明符;使用%u
打印无符号值。无符号整数i=-2;
因为隐式转换(按调整范围)请记住这里的-
是一个运算符。simple2
也被签署,对于assign unsigned,您应该这样做:unsigned int i=2u
。请记住signed
和unsigned
之间的重要区别,它们的范围!您所说的未定义行为是什么意思?它打印出来了-2。您的意思是事情可能会发生?@GeorgeNewton是的,任何事情都可能发生,添加链接。@GeorgeNewton:“未定义的行为”,因为它经常用于回答C问题,这意味着C标准对行为没有任何要求。这并不意味着任何事情都可能发生,因为C实现、计算系统、逻辑和物理定律仍然有要求。@GeorgeNewton“未定义的行为”这意味着任何东西都可以打印,包括打印您认为正确的值。但是,这种行为是不可移植的。例如,在负片表示为符号+值的硬件上,打印的数字会有所不同。@Eric Postchil我不得不同意,措辞过于夸张,您的措辞更加精确。There在printf(“%d”,i);
中没有强制转换。也没有转换。在许多C实现中,会将字节重新解释为不同的类型,但C标准不能保证这一点。“将字节重新解释为不同的类型”称为强制转换。不是吗?没有。强制转换是在C 2011(N1570)中定义的6.5.4.他们有形式“(类型)表达”。演员歌剧