计算C中变量类型的范围



这里的一位业余爱好者对nooby问题感到抱歉。K&R例2-1。使用表头常量和/或直接计算来计算各种变量类型(char、short、int、long(+浮动类型的范围。我使用limites.h常量打印固定宽度变量类型的范围以供参考。我仍然需要检查IEEE754。

对于所需的结果,我的max函数会给我少1,比如:0xfe、0xfffe等,因此出于某种原因,LSB不会切换到1。为什么?昨天,在思考这个问题时,我想到了使用void*类型将各种变量类型传递给min-max函数的想法。为了能够取消对存储不同长度的固定宽度数字地址的void*类型的限制,我想简单地将其转换为size_t*类型,不知何故,它确实有效,但我不知道为什么。这是合法的吗?我从来没有在我的C编程书中见过。如果它不合法,还有什么其他可能性可以取消对无效类型的限制?

我不希望使用循环和检查溢出,这种方法非常慢。


#include <stdio.h>
#include <float.h>
#include <limits.h>
void unsigned_max(void* data_ptr, size_t data_size) {
int bit = ((int)data_size * 8) - 1;
while(bit) {
*(size_t*)data_ptr |= 1 << bit;
bit--;
}
}
void unsigned_min(void* data_ptr, size_t data_size) {
int bit = ((int)data_size * 8) - 1;
while(bit){
*(size_t*)data_ptr &= 0 << bit;
bit--;
}
}
void signed_min(void* data_ptr, size_t data_size) {
int bit = ((int)data_size * 8) - 1;
*(size_t*)data_ptr |= 1 << bit;
bit--;
while (bit) {
*(size_t*)data_ptr |= 0 << bit;
bit--;
}
}
void signed_max(void* data_ptr, size_t data_size) {
int bit = ((int)data_size * 8) - 1;
*(size_t*)data_ptr &= 0 << bit;
bit--;
while (bit) {
*(size_t*)data_ptr |= 1 << bit;
bit--;
}
}
int main(void) {
unsigned char u_byte = 0;
char byte = 0;
unsigned short ushort_intgr = 0;
short short_intgr = 0;
unsigned int u_intgr = 0;
int intgr = 0;
unsigned long ulong_intgr = 0;
long long_intgr = 0;
char str_output[18] = "Min-max range of";
char delimiter[18] =  "================";
/*
* Print ranges of unsigned and signed instances of char, short, int and long
* variables using limits.h constants.
*/

printf("%s unsigned char:n%x,%xn", str_output, u_byte, UCHAR_MAX);
printf("%s signed char:n%x,%xn", str_output, CHAR_MIN, CHAR_MAX);
printf("%s unsigned short:n%x,%xn", str_output, ushort_intgr, USHRT_MAX);
printf("%s signed short:n%x,%xn", str_output, SHRT_MIN, SHRT_MAX);
printf("%s unsigned int:n%x,%xn", str_output, u_intgr, UINT_MAX);
printf("%s signed int:n%x,%xn", str_output, INT_MIN, INT_MAX);
printf("%s unsigned long:n%x,%xn", str_output, ulong_intgr, ULONG_MAX);
printf("%s signed long:n%x,%xn", str_output, LONG_MIN, LONG_MAX);


printf("%sn", delimiter);
/*
* Print ranges of unsigned and signed instances of char, short, int and long
* variables using bitwise operations.
*/
printf("%s unsigned char:n%d,", str_output, u_byte);
unsigned_max(&u_byte, sizeof(u_byte));
printf("%xn", u_byte);
printf("%s signed char:n", str_output);
signed_min(&u_byte, sizeof(u_byte));
printf("%x,", u_byte);
signed_max(&u_byte, sizeof(u_byte));
printf("%xn", u_byte);
printf("%s unsigned short:n%d,", str_output, ushort_intgr);
unsigned_max(&ushort_intgr, sizeof(ushort_intgr));
printf("%xn", ushort_intgr);
printf("%s signed short:n", str_output);
signed_min(&short_intgr, sizeof(short_intgr));
printf("%x,", short_intgr);
signed_max(&short_intgr, sizeof(short_intgr));
printf("%xn", short_intgr);
printf("%s unsigned int:n%u,", str_output, u_intgr);
unsigned_max(&u_intgr, sizeof(u_intgr));
printf("%xn", u_intgr);
printf("%s signed int:n", str_output);
signed_min(&intgr, sizeof(intgr));
printf("%x,", intgr);
signed_max(&intgr, sizeof(intgr));
printf("%xn", intgr);
printf("%s unsigned long:n%lu,", str_output, ulong_intgr);
unsigned_max(&ulong_intgr, sizeof(ulong_intgr));
printf("%xn", ulong_intgr);
printf("%s signed long:n", str_output);
signed_min(&long_intgr, sizeof(long_intgr));
printf("%x,", long_intgr);
signed_max(&long_intgr, sizeof(long_intgr));
printf("%xn", long_intgr);
return 0;
}

我的输出是:

Min-max range of unsigned char:
0,ff
Min-max range of signed char:
ffffff80,7f
Min-max range of unsigned short:
0,ffff
Min-max range of signed short:
ffff8000,7fff
Min-max range of unsigned int:
0,ffffffff
Min-max range of signed int:
80000000,7fffffff
Min-max range of unsigned long:
0,ffffffff
Min-max range of signed long:
80000000,7fffffff
================
Min-max range of unsigned char:
0,fe
Min-max range of signed char:
fe,7e
Min-max range of unsigned short:
0,fffe
Min-max range of signed short:
ffff8000,7ffe
Min-max range of unsigned int:
0,fffffffe
Min-max range of signed int:
80000000,7ffffffe
Min-max range of unsigned long:
0,fffffffe
Min-max range of signed long:
80000000,7ffffffe

我还看了K&R解决方案书,作者通常用优雅的一句话解决所有问题。当我运行它时,它似乎不起作用,为最小值和最大值返回零。我知道-0是每个比特在补码形式中都是真的。那时候-0可以存储为0x1111?所以0x1111>gt;1=0x0111;0x0111*(-1(=0x1000?

printf("signed char min = %dn", -(char)((unsigned char) -0 >> 1));
printf("signed char max = %dn", (char)((unsigned char) -0 >> 1));
printf("unsigned char max = %un", (unsigned char) -0);
...

在2的补码机上,您需要

printf("signed char min:        %hhdn", -(signed char)((unsigned char)~0 >> 1) - 1);
printf("signed char max:        %hhdn", (signed char)((unsigned char)~0 >> 1));
printf("unsigned char max:      %hhun", (unsigned char)~0);
printf("signed short min:       %hdn", -(signed short)((unsigned short)~0 >> 1) - 1);
printf("signed short max:       %hdn", (signed short)((unsigned short)~0 >> 1));
printf("unsigned short max:     %hun", (unsigned short)~0);
printf("signed int min:         %dn", -(signed int)(~0U >> 1) - 1);
printf("signed int max:         %dn", (signed int)(~0U >> 1));
printf("unsigned int max:       %un", ~0U);
printf("signed long min:        %ldn", -(signed long)(~0UL >> 1) - 1);
printf("signed long max:        %ldn", (signed long)(~0UL >> 1));
printf("unsigned long max:      %lun", ~0UL);
printf("signed long long min:   %lldn", -(signed long long)(~0ULL >> 1) - 1);
printf("signed long long max:   %lldn", (signed long long)(~0ULL >> 1));
printf("unsigned long long max: %llun", ~0ULL);

演示

注意:char并不总是与signed char相同,因此我们需要使用signed char。然而,我们可以简单地使用shortint来代替signed shortsigned int


也就是说,正确且独立于平台的方法是使用编译器提供的定义。

#include <limits.h>
printf("signed char min:        %hhdn", SCHAR_MIN);
printf("signed char max:        %hhdn", SCHAR_MAX);
printf("unsigned char max:      %hhun", UCHAR_MAX);
printf("signed char min:        %hdn", SHRT_MIN);
printf("signed char max:        %hdn", SHRT_MAX);
printf("unsigned char max:      %hun", USHRT_MAX);
printf("signed int min:         %dn", INT_MIN);
printf("signed int max:         %dn", INT_MAX);
printf("unsigned int max:       %un", UINT_MAX);
printf("signed long min:        %ldn", LONG_MIN);
printf("signed long max:        %ldn", LONG_MAX);
printf("unsigned long max:      %lun", ULONG_MAX);
printf("signed long long min:   %lldn", LLONG_MIN);
printf("signed long long max:   %lldn", LLONG_MAX);
printf("unsigned long long max: %llun", ULLONG_MAX);

演示

最新更新