C中如何确定unsigned char的范围?
How can I confirm the range of unsigned char in C?
我的编译器的无符号字符包含 1 个字节。
据我所知,unsigned char 的范围是从 0 到 2^8 - 1,即 255。
现在我想确认 unsigned char 可以显示的最大整数是 255。
以下是我的代码:
#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;
}
输出为
unsigned char has 1 bytes.
-1
4294967295
4294967295
4294967295
4294967295
4294967295 是 2^32 - 1
我哪里做错了?
首先,当您将小于 int
的整数参数传递给可变参数函数(如 printf
)时,它会自动提升为 int
.
其次,当您使用算术时,较小的整数类型 再次 被提升为 int
。
阅读例如this implicit conversion reference 获取更多信息。
如果要打印 char
(或者更确切地说 unsigned char
)值,则需要使用格式说明符的 hh
前缀(参见 this printf
and family reference) :
printf("%hhu\n", (unsigned char) (a - 1));
a-1
这是算术运算,会发生隐式转换。编译器会将其视为整数。尝试将 -1 分配给无符号类型,然后检查该值。您还应该注意到 printf 操作数,例如 %d,对于该特定示例,它需要整数。
您的代码调用了 undefined behaviour 因为您使用了错误的 printf 格式说明符。
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 :
[...] If any argument is not the correct type for the corresponding
conversion specification, the behavior is undefined.
你的知识在微妙的方面是不完整的:
The unsigned char
for my compiler contains 1 byte.
类型 unsigned char
根据定义 对于所有编译器正好是一个字节。
So as per my knowledge the range of unsigned char is from 0 to 2^8 - 1 which is 255
.
不完全是:unsigned char
的 最小 值位数是 8
并且此类型不允许填充位,这意味着 最小 字节 的大小是 8 位。事实上,现在大多数架构都标准化为 8 位字节,但 C 标准允许其他更大的位宽,并且一些微控制器使用 16 位字节(甚至 32 位字节)。在这样的处理器上,unsigned char
为 16 位(甚至 32 位)。
Now I want to confirm the max integer unsigned char
can display is 255
.
这是一个真正的问题,可以在编译时和运行时验证。
The following is my code:
#include <stdio.h>
#include <limits.h>
包含 <limits.h>
是一个很好的方法:UCHAR_MAX
是您要在预处理指令中直接打印甚至测试的值。
int main(void) {
printf("unsigned char has %d bytes.\n", sizeof(unsigned char));
未定义的行为:%d
需要类型为 int
的参数,它与类型为 size_t
的 sizeof(unsigned char)
不同并且可能不兼容。使用 %zu
或将参数转换为 (int)sizeof(unsigned char)
。但是请注意,sizeof(unsigned char)
根据定义 始终计算为 1
类型 size_t
.
unsigned char a;
a = 0;
printf("%d\n", a - 1);
a - 1
始终计算为 -1
,因为 a
被提升为 int
,并且 0 - 1
的值为 -1
。您想要打印 (unsigned char)(a - 1)
,或者只是 (unsigned char)-1
.
printf("%u\n", a - 1);
这将打印 (unsigned int)-1
的值,即 UINT_MAX
,而不是 UCHAR_MAX
。
printf("%lu\n", a - 1);
printf("%llu\n", a - 1);
printf("%zu\n", a - 1);
上面的 3 个 printf
调用具有潜在的未定义行为,因为您为预期字节分别为 unsigned long
、unsigned long long
和 [= 的参数传递了 int
值31=].
return 0;
}
这里有一个更简单的方法:
#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;
}
输出:
UCHAR_MAX = 255
(unsigned char)-1 = 255
-1 with %hhu conversion: 255
我的编译器的无符号字符包含 1 个字节。
据我所知,unsigned char 的范围是从 0 到 2^8 - 1,即 255。
现在我想确认 unsigned char 可以显示的最大整数是 255。
以下是我的代码:
#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;
}
输出为
unsigned char has 1 bytes.
-1
4294967295
4294967295
4294967295
4294967295
4294967295 是 2^32 - 1
我哪里做错了?
首先,当您将小于 int
的整数参数传递给可变参数函数(如 printf
)时,它会自动提升为 int
.
其次,当您使用算术时,较小的整数类型 再次 被提升为 int
。
阅读例如this implicit conversion reference 获取更多信息。
如果要打印 char
(或者更确切地说 unsigned char
)值,则需要使用格式说明符的 hh
前缀(参见 this printf
and family reference) :
printf("%hhu\n", (unsigned char) (a - 1));
a-1
这是算术运算,会发生隐式转换。编译器会将其视为整数。尝试将 -1 分配给无符号类型,然后检查该值。您还应该注意到 printf 操作数,例如 %d,对于该特定示例,它需要整数。
您的代码调用了 undefined behaviour 因为您使用了错误的 printf 格式说明符。
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 :
[...] If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
你的知识在微妙的方面是不完整的:
The
unsigned char
for my compiler contains 1 byte.
类型 unsigned char
根据定义 对于所有编译器正好是一个字节。
So as per my knowledge the range of unsigned char is from 0 to 2^8 - 1 which is
255
.
不完全是:unsigned char
的 最小 值位数是 8
并且此类型不允许填充位,这意味着 最小 字节 的大小是 8 位。事实上,现在大多数架构都标准化为 8 位字节,但 C 标准允许其他更大的位宽,并且一些微控制器使用 16 位字节(甚至 32 位字节)。在这样的处理器上,unsigned char
为 16 位(甚至 32 位)。
Now I want to confirm the max integer
unsigned char
can display is255
.
这是一个真正的问题,可以在编译时和运行时验证。
The following is my code:
#include <stdio.h> #include <limits.h>
包含 <limits.h>
是一个很好的方法:UCHAR_MAX
是您要在预处理指令中直接打印甚至测试的值。
int main(void) { printf("unsigned char has %d bytes.\n", sizeof(unsigned char));
未定义的行为:%d
需要类型为 int
的参数,它与类型为 size_t
的 sizeof(unsigned char)
不同并且可能不兼容。使用 %zu
或将参数转换为 (int)sizeof(unsigned char)
。但是请注意,sizeof(unsigned char)
根据定义 始终计算为 1
类型 size_t
.
unsigned char a; a = 0; printf("%d\n", a - 1);
a - 1
始终计算为 -1
,因为 a
被提升为 int
,并且 0 - 1
的值为 -1
。您想要打印 (unsigned char)(a - 1)
,或者只是 (unsigned char)-1
.
printf("%u\n", a - 1);
这将打印 (unsigned int)-1
的值,即 UINT_MAX
,而不是 UCHAR_MAX
。
printf("%lu\n", a - 1); printf("%llu\n", a - 1); printf("%zu\n", a - 1);
上面的 3 个 printf
调用具有潜在的未定义行为,因为您为预期字节分别为 unsigned long
、unsigned long long
和 [= 的参数传递了 int
值31=].
return 0; }
这里有一个更简单的方法:
#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;
}
输出:
UCHAR_MAX = 255
(unsigned char)-1 = 255
-1 with %hhu conversion: 255