简体   繁体   English

如何确认C中unsigned char的范围?

[英]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 is 255 . 现在我想确认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被提升为int0 - 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 longunsigned long longsize_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM