考虑以下两个C程序.我的问题是在第一个程序unsigned关键字打印,-12但我认为它应该打印4294967284但它不打印它为%d说明符.它打印它为%u说明符.但是如果我们看第二个程序,输出144应该是它应该的位置-112.有关unsigned关键字的东西很可疑,我没有得到.任何帮助的朋友!
#include <stdio.h>
int main()
{ unsigned int i = -12;
printf(" i = %d\n",i);
printf(" i = %u\n",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在prorgam之上,我从这个链接获得:为负号分配一个无符号的int?
#include <stdio.h>
int main(void)
{unsigned char a=200, b=200, c;
c = a+b;
printf("result=%d\n",c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Kei*_*son 12
每个printf格式说明符都需要某个特定类型的参数."%d"需要一个类型的参数int; "%u"需要一个类型的参数unsigned int.传递正确类型的参数完全是您的责任.
unsigned int i = -12;
Run Code Online (Sandbox Code Playgroud)
-12是类型的int.初始化隐式地将该值转换int为unsigned int.转换后的值(正数和非常大)存储在i.如果int和unsigned int是32位的,所存储的值将是4294967284(2 32 -12).
printf(" i = %d\n",i);
Run Code Online (Sandbox Code Playgroud)
i属于类型unsigned int,但"%d"需要int参数.行为不是由C标准定义的.通常,存储的值i将被解释为好像它已存储在int对象中.在大多数系统上,输出将是i = -12- 但你不应该依赖它.
printf(" i = %u\n",i);
Run Code Online (Sandbox Code Playgroud)
这将正确打印值i(假设前一个语句的未定义行为没有弄乱).
对于普通函数,假设您正确调用它们,如果可以进行转换,则通常会将参数隐式转换为参数的声明类型.对于可变参数函数printf,可以采用不同数量和类型的参数,不能进行这样的转换,因为编译器不知道预期的类型.相反,参数经历默认参数促销.狭义的类型的参数int被提升为intif,int可以包含该类型的所有值,或者unsigned int否则.类型的参数float被提升为double(这就是为什么"%f"适用于float和double参数).
规则是这样一个狭义的无符号类型的参数通常(但不总是)被提升为(签名)int.
unsigned char a=200, b=200, c;
Run Code Online (Sandbox Code Playgroud)
假设8位字节,a并b设置为200.
c = a+b;
Run Code Online (Sandbox Code Playgroud)
总和400太多了,不适合unsigned char.对于无符号算术和转换,超出范围的结果将减少到该类型的范围.c设置为144.
printf("result=%d\n",c);
Run Code Online (Sandbox Code Playgroud)
价值c被提升为int; 即使参数是无符号类型,int也足以容纳该类型的所有可能值.输出是result=144.
在第一个程序中,行为未定义.您有责任确保格式说明符与参数的数据类型匹配.编译器会发出代码,假设你做对了; 在运行时它不必进行任何检查(通常,即使它想要也不能进行任何检查).
(例如,库实现printf函数不知道你给它的参数,它只看到一些字节,它必须假设那些是你指定的类型的字节%d).
您似乎试图unsigned根据具有未定义行为的程序的输出推断某些方法.那不行.坚持明确定义的程序(最好只读取定义unsigned).
在评论中你说:
可以给我任何unsigned关键字的参考.仍然没有让我理解这个概念.C/C++标准中的无符号定义.
在C99标准中,阅读第6.2.5节,从第6部分开始.
定义unsigned int是一个整数类型,它可以保存从0最高到正数的值UINT_MAX(应该比2的幂小1),这必须至少是65535,通常是4294967295.
编写时unsigned int i = -12;,编译器会看到它-12超出允许值范围unsigned int,并执行转换.该转换的定义是加或减,UINT_MAX+1直到该值在范围内.
你问题的第二部分与这一切无关.unsigned int该计划中没有; 只unsigned char.
在那个程序中,200 + 200给出400.如上所述,由于这超出范围,编译器通过减去UCHAR_MAX+1(即256)直到它在范围内来转换它.400 - 256 = 144.