thr*_*eaz 1 c variables limits
我正在努力确定每个变量的边缘大小.我无法理解以下问题.
例如,为了获得char的最大值,我使用:~ 0 >> 1
哪个应该像这样工作:
现在我想用printf函数呈现这个结果.为什么我必须像这样使用演员:
printf("%d\n", (unsigned char)(~0) >> 1)?
我只是不明白.当我离开char范围时,我认为它与第2点有关,但我不确定.
如果你向我提出更复杂的解释,我将不胜感激.
请不要使用这些技巧.它们可能在普通机器上工作,但它们可能不可移植且难以理解.而是使用头文件中的符号常量,limits.h其中包含每种基本类型的大小限制.例如,CHAR_MAX是上界为一个char,CHAR_MIN是下界.对于数值类型进一步限制在声明stddef.h和stdint.h中可以找到stdint.h.
现在提出您的问题:int默认情况下,算术是在类型的值上完成的,除非您使涉及的操作数具有不同的类型.这种情况由于各种原因而发生,例如涉及具有不同类型的变量之一或使用不同类型的迭代(如1.0或1L或1U).更重要的是,算术表达式的类型从内到外都有所提升.因此,在声明中
char c = 1 + 2 + 3;
Run Code Online (Sandbox Code Playgroud)
表达式1 + 2 + 3被计算为类型,int并且仅char在分配之前立即转换为表达式.更重要的是,在C语言中,你不能对小于的类型进行算术运算int.例如,在表达c + 1其中c的类型的char,编译器插入一个隐式转换从char到int加一来之前c.因此,一个声明就好
c = c + 1;
Run Code Online (Sandbox Code Playgroud)
实际上在C中表现如下:
c = (char)((int)c + 1);
Run Code Online (Sandbox Code Playgroud)
因此,~0 >> 1实际上0xffffffff在通常的32位架构上求值为(-1),因为该类型int通常具有32位,并且有符号类型的右移通常移位符号位,因此最高有效位变为1.转换为unsigned char导致截断,结果为0xff(255).所有参数,但是第一至printf是一个的一部分变量参数列表这是有点复杂,但基本上是指所有类型的小比int被转换到int,float被转换为double和所有其他类型保持不变.
现在,我们怎样才能做到这一点?在具有二进制补码和无填充位的普通机器上,可以使用这些表达式来计算最大和最小char,假设sizeof (char) < sizeof (int):
(1 << CHAR_BIT - 1) - 1; /* largest char */
-(1 << CHAR_BIT - 1); /* smallest char */
Run Code Online (Sandbox Code Playgroud)
对于其他类型,由于我们需要避免溢出,因此这将稍微困难一些.这是一个适用于普通机器上所有有符号整数类型的表达式,其中type您希望具有以下限制的类型:
(type)(((uintmax_t)1 << sizeof (type) * CHAR_BIT - 1) - 1) /* largest */
(type)-((uintmax_t)1 << sizeof (type) * CHAR_BIT - 1) /* smallest */
Run Code Online (Sandbox Code Playgroud)
对于无符号类型type,您可以使用它来获得最大值:
~(type)0
Run Code Online (Sandbox Code Playgroud)
请注意,所有这些技巧应该不会出现在移植的代码.