[英]How can I confirm the range of unsigned char in C?
The unsigned char for my compiler contains 1 byte. 我的编译器的unsigned char包含1个字节。
So as per my knowledge the range of unsigned char is from 0 to 2^8 - 1 which is 255. 所以据我所知,unsigned char的范围是0到2 ^ 8 - 1,即255。
Now I want to confirm the max integer unsigned char can display is 255. 现在我想确认无符号字符的最大整数可以显示为255。
The following is my code: 以下是我的代码:
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("unsigned char has %d bytes.\n", sizeof(unsigned char));
unsigned char a;
a = 0;
printf("%d\n", a - 1);
printf("%u\n", a - 1);
printf("%lu\n", a - 1);
printf("%llu\n", a - 1);
printf("%zu\n", a - 1);
return 0;
}
The output is 输出是
unsigned char has 1 bytes.
-1
4294967295
4294967295
4294967295
4294967295
4294967295 is 2^32 - 1 4294967295是2 ^ 32 - 1
Where did I go wrong? 我哪里做错了?
First of all, when you pass an integer argument smaller than int
to a variadic function (like printf
) then it's automatically promoted to an int
. 首先,当您将小于
int
的整数参数传递给可变参数函数(如printf
)时,它会自动提升为int
。
Secondly, when you use arithmetic, smaller integer types again are promoted to int
. 其次,当您使用算术时,较小的整数类型将再次提升为
int
。
Read eg this implicit conversion reference for more information. 有关详细信息,请阅读此隐式转换参考 。
If you want to print the char
(or rather unsigned char
) value you need to use the hh
prefix for the format specifier (see eg this printf
and family reference ): 如果要打印
char
(或者更确切地说是unsigned char
)值,则需要使用格式说明符的hh
前缀(请参阅此printf
和系列引用 ):
printf("%hhu\n", (unsigned char) (a - 1));
a-1
This is arithmetic operation and implicit conversion takes place. 这是算术运算并且发生隐式转换。 Compiler will treat it as integer.
编译器会将其视为整数。 Try to assign -1 to unsigned type, then check the value.
尝试将-1分配给无符号类型,然后检查该值。 You should also notice the printf operands, like %d, which for that particular example, expects integer.
您还应该注意到printf操作数,例如%d,对于该特定示例,它应该是整数。
Your knowledge is incomplete in subtle ways: 您的知识在细微方面是不完整的:
The
unsigned char
for my compiler contains 1 byte.我的编译器的
unsigned char
包含1个字节。
Type unsigned char
is by definition exactly one byte for all compilers. 根据定义,类型
unsigned char
恰好是所有编译器的一个字节。
So as per my knowledge the range of unsigned char is from 0 to 2^8 - 1 which is
255
.所以据我所知,unsigned char的范围是0到2 ^ 8 - 1,即
255
。
Not exactly: the minimum number of value bits for unsigned char
is 8
and no padding bits are allowed for this type, which means the minimum size for a byte is 8 bits. 不完全是:
unsigned char
的最小值位数为8
并且此类型不允许填充位,这意味着一个字节的最小大小为8位。 Indeed most architectures nowadays standardize on 8-bit bytes, but the C Standard allows for other, larger, bit widths, and some micro-controllers use 16-bit bytes (or even 32-bit bytes). 实际上,现在大多数架构都标准化为8位字节,但C标准允许其他更大的位宽,而一些微控制器则使用16位字节(甚至32位字节)。 On such processors,
unsigned char
as 16 bits (or even 32 bits). 在这样的处理器上,
unsigned char
为16位(甚至32位)。
Now I want to confirm the max integer
unsigned char
can display is255
.现在我想确认
unsigned char
的最大整数可以显示为255
。
This is a genuine concern that can be validated both at compile time and at runtime. 这是一个真正的问题,可以在编译时和运行时进行验证。
The following is my code:
以下是我的代码:
#include <stdio.h> #include <limits.h>
Including <limits.h>
is a good approach: UCHAR_MAX
is the value you want to print or even test directly in a preprocessing directive. 包括
<limits.h>
是一种很好的方法: UCHAR_MAX
是您要在预处理指令中打印甚至直接测试的值。
int main(void) { printf("unsigned char has %d bytes.\\n", sizeof(unsigned char));
Undefined behavior: %d
expects an argument of type int
, which is different and potentially incompatible with sizeof(unsigned char)
that has type size_t
. 未定义的行为:
%d
需要int
类型的参数,该参数与size_t
类型的sizeof(unsigned char)
不同且可能不兼容。 Use %zu
or cast the argument as (int)sizeof(unsigned char)
. 使用
%zu
或将参数转换为(int)sizeof(unsigned char)
。 Note however that sizeof(unsigned char)
by definition always evaluates to 1
with type size_t
. 但请注意, 按定义 ,
sizeof(unsigned char)
的值始终为1
,类型为size_t
。
unsigned char a; a = 0; printf("%d\\n", a - 1);
a - 1
always evaluates to -1
as a
is promoted to int
and 0 - 1
has a value of -1
. a - 1
总是求值为-1
因为a
被提升为int
, 0 - 1
的值为-1
。 You want instead to print (unsigned char)(a - 1)
, or simply (unsigned char)-1
. 你想要打印
(unsigned char)(a - 1)
,或简单地(unsigned char)-1
。
printf("%u\\n", a - 1);
This will print the value of (unsigned int)-1
, which is UINT_MAX
, not UCHAR_MAX
. 这将打印
(unsigned int)-1
的值,即UINT_MAX
,而不是UCHAR_MAX
。
printf("%lu\\n", a - 1); printf("%llu\\n", a - 1); printf("%zu\\n", a - 1);
The 3 printf
calls above have potential undefined behavior because you pass an int
value for an argument whose expected byte is respectively unsigned long
, unsigned long long
and size_t
. 上面的3个
printf
调用具有潜在的未定义行为,因为为预期字节分别为unsigned long
, unsigned long long
和size_t
的参数传递int
值。
return 0; }
Here is a simpler approach: 这是一个更简单的方法:
#include <stdio.h>
#include <limits.h>
int main() {
printf("UCHAR_MAX = %u\n", UCHAR_MAX);
printf("(unsigned char)-1 = %u\n", (unsigned char)-1);
printf("-1 with %%hhu conversion: %hhu\n", -1);
return 0;
}
Output: 输出:
UCHAR_MAX = 255
(unsigned char)-1 = 255
-1 with %hhu conversion: 255
Your code invoked undefined behaviour because You have used wrong format specifier of printf. 您的代码调用了未定义的行为,因为您使用了错误的printf格式说明符。
GCC Compiler warnings: GCC编译器警告:
prog.c: In function 'main':
prog.c:5:32: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=]
printf("unsigned char has %d bytes.\n", sizeof(unsigned char));
~^ ~~~~~~~~~~~~~~~~~~~~~
%ld
prog.c:13:15: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'int' [-Wformat=]
printf("%lu\n", a - 1);
~~^ ~~~~~
%u
prog.c:14:16: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 2 has type 'int' [-Wformat=]
printf("%llu\n", a - 1);
~~~^ ~~~~~
%u
prog.c:15:15: warning: format '%zu' expects argument of type 'size_t', but argument 2 has type 'int' [-Wformat=]
printf("%zu\n", a - 1);
~~^ ~~~~~
%u
C11 $7.19.6.1 p9 : C11 $ 7.19.6.1 p9:
[...] If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
[...]如果任何参数不是相应转换规范的正确类型,则行为未定义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.