【发布时间】:2022-01-07 05:48:39
【问题描述】:
这里是一个业余爱好者,很抱歉提出这个问题。 K&R前。 2-1。使用标头常量和/或直接计算来计算各种变量类型(char、short、int、long)+ 浮点类型的范围。我使用limits.h 常量来打印固定宽度变量类型的范围以供参考。而且我还要检查 IEEE754。
我的最大函数为我期望的结果少了 1,例如:0xfe、0xfffe 等,所以由于某种原因,LSB 没有切换到 1。为什么会这样?昨天,在思考这个问题时,我想到了使用 void* 类型将各种变量类型传递给 min-max 函数的想法。为了能够取消对具有不同长度的固定宽度数字的 void* 类型存储地址的引用,我的想法是将其简单地转换为 size_t* 类型,并且它以某种方式工作,我不知道为什么。这是否合法,我从未在我的 C 编程书籍中看到它。如果它不合法,还有什么其他的可能性可以取消对 void* 类型的引用?
我不希望使用循环和检查溢出,这种方法很慢。
#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,%x\n", str_output, u_byte, UCHAR_MAX);
printf("%s signed char:\n%x,%x\n", str_output, CHAR_MIN, CHAR_MAX);
printf("%s unsigned short:\n%x,%x\n", str_output, ushort_intgr, USHRT_MAX);
printf("%s signed short:\n%x,%x\n", str_output, SHRT_MIN, SHRT_MAX);
printf("%s unsigned int:\n%x,%x\n", str_output, u_intgr, UINT_MAX);
printf("%s signed int:\n%x,%x\n", str_output, INT_MIN, INT_MAX);
printf("%s unsigned long:\n%x,%x\n", str_output, ulong_intgr, ULONG_MAX);
printf("%s signed long:\n%x,%x\n", str_output, LONG_MIN, LONG_MAX);
printf("%s\n", 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("%x\n", 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("%x\n", u_byte);
printf("%s unsigned short:\n%d,", str_output, ushort_intgr);
unsigned_max(&ushort_intgr, sizeof(ushort_intgr));
printf("%x\n", 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("%x\n", short_intgr);
printf("%s unsigned int:\n%u,", str_output, u_intgr);
unsigned_max(&u_intgr, sizeof(u_intgr));
printf("%x\n", u_intgr);
printf("%s signed int:\n", str_output);
signed_min(&intgr, sizeof(intgr));
printf("%x,", intgr);
signed_max(&intgr, sizeof(intgr));
printf("%x\n", intgr);
printf("%s unsigned long:\n%lu,", str_output, ulong_intgr);
unsigned_max(&ulong_intgr, sizeof(ulong_intgr));
printf("%x\n", 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("%x\n", 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 >> 1 = 0x0111; 0x0111*(-1) = 0x1000?
printf("signed char min = %d\n", -(char)((unsigned char) -0 >> 1));
printf("signed char max = %d\n", (char)((unsigned char) -0 >> 1));
printf("unsigned char max = %u\n", (unsigned char) -0);
...
【问题讨论】:
-
以signed short为例,
ffff8000不可能是正确的,因为它有4个字节而不是2个。但是低2个字节很好。 -
应该是~0,而不是-0(至少在二进制补码机器上)。
-
嗯,有道理,我的解决方案书的 pdf 副本质量很差。
-
...除了这还不够,给出 -127 和 127
-
把
while (bit)改成while (bit >= 0),因为1是1 << 0。
标签: c void-pointers kernighan-and-ritchie