尝试获取无符号long long的最大位数时的奇怪行为

时间:2015-03-18 15:25:43

标签: c variables terminate

我喜欢奢侈品。我想为您创建一种获取unsigned long long int最大拥有位数的方法。一切都是自动的。 这是:

#include <limits.h>
#include <string.h>

#define STRINGIFY(x) #x
#define ULLONG_MAX_STRING STRINGIFY(ULLONG_MAX)
#define NUMERAL_MAXIMUM strlen(ULLONG_MAX_STRING)

这是否按照描述工作?


现在关于奇怪的行为几乎回答了上面的问题。 如果我声明一个这样的变量(-std=c99 specific):

char variable [NUMERAL_MAXIMUM];

它不是声明自动范围的变量,大小为20的数组,而是在它到达该行之前终止程序。虽然我没有像这样声明变量,但没有任何内容终止,程序继续工作。


发生了什么事?


更新:更奇怪的是,只有当我将获得的长度用作数组的大小时,程序才会这样做。

4 个答案:

答案 0 :(得分:1)

IIUC,OQ想要打印十进制最大值所需的大小。以下适用于8位到64位的大小,至少对于CHAR_BIT==8

#include <stdio.h>
#include <limits.h>

#define ASCII_SIZE(s) ((3+(s) * CHAR_BIT) *4 / 13)

int main(void)
{
printf("unsigned char : %zu\n", ASCII_SIZE(sizeof(unsigned char)) );
printf("unsigned short int : %zu\n", ASCII_SIZE(sizeof(unsigned short int)) );
printf("unsigned int : %zu\n", ASCII_SIZE(sizeof(unsigned int)) );
printf("unsigned long : %zu\n", ASCII_SIZE(sizeof(unsigned long)) );
printf("unsigned long long : %zu\n", ASCII_SIZE(sizeof(unsigned long long)) );

printf("          Ding : %u\n", UINT_MAX );
printf("     Lang Ding : %lu\n", ULONG_MAX );
printf("Heel lang Ding : %llu\n", ULLONG_MAX );

return 0;
}

输出:

unsigned char : 3
unsigned short int : 5
unsigned int : 10
unsigned long : 20
unsigned long long : 20
          Ding : 4294967295
     Lang Ding : 18446744073709551615
Heel lang Ding : 18446744073709551615

答案 1 :(得分:0)

使用定义时,您必须知道在编译开始之前它已经过预处理。

这意味着它可能变得非常难以调试,因为代码只是粘贴在那里而且编译器没有检查语义,类型错误等。

尝试打印ULLONG_MAX及其strlen。当你使用STRINGIFY时,如果这些都没有奇怪的值,请查看。

答案 2 :(得分:0)

我不知道是什么原因导致你的崩溃。要调查我首先要查看预处理器输出(cc -E

但更重要的是,你的整个方法都是错误的。 ULLONG_MAX的预处理器扩展的长度不保证与格式化为十进制数字字符串的该数字的长度有任何关系。我检查的第一个系统有这个:

#define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
完全展开的

成为:

(9223372036854775807LL * 2ULL + 1)

如果你设法获得strlen,那么它会比18446744073709551615的长度大一点,这个数字是相同的数字,以你可能想到的方式表示。

这意味着你的缓冲区可能太大了。但它也可能太小了。想想#define ULLONG_MAX 0xffffffffffffffff的可能性。

您需要使用数字运算来计算缓冲区大小,而不是字符串运算。正整数n的十进制表示中的位数是ceil(log10(n))+1。您无法在预处理器中完全执行该计算,因为它不执行浮点运算。但你可以做一个合理的近似。

ULLONG_MAX的基数2表示中的位数是类型中的位数:sizeof(unsigned long long)*CHAR_BIT。小数位数大致是基数2位数log(2)/log(10)的数量。现在,wildplasser刚刚发布了答案,所以我会在这里停下来指出log(2)/log(10)略低于4/13,这就是为什么wildplasser的答案有效。

答案 3 :(得分:0)

您必须再次展开STRINGIFY的参数以获得常量

的值
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)

然后在这里你应该使用sizeof运算符

#define ULLONG_MAX_STRING STRINGIFY(ULLONG_MAX)
#define NUMERAL_MAXIMUM (sizeof(ULLONG_MAX_STRING)-1)

在编译时完成所有工作。