c语言 - 为什么不能在动态分配的内存块中存储非常大的单个值?



为什么我不能在这个分配的内存块中存储一个大整数?

int *dyn = malloc(16);
*dyn = 9999999999;
printf("%llin", *dyn);
free(dyn);

在编译时,GCC警告我将发生整数溢出。果不其然,当打印出来时,它已经溢出了。

为什么我不能使用整个内存块来存储单个值?

*dyn = 9999999999;不会指示计算机使用为dyn分配的所有内存来存储值9999999999。

在C中,dyn有一个类型。类型为"指向int的指针"。然后*dyn具有类型int,其具有特定的、固定数量的比特。它没有表示"为dyn分配的所有内存"的类型。

由于*dynint*dyn = 9999999999;告诉计算机将9999999999放入int。由于9999999999对于C实现中的int来说太大,因此会发生溢出。

我们可以对计算机进行编程,并设计编程语言来管理任意大小的整数。有些语言,比如Python,就是这样做的。然而,这需要额外的软件,尤其是当程序运行时,为了处理出现的任何大小的数字,必须做一些可变工作量的软件。C被设计成一种基本语言。它处理特定大小的对象,通常将C代码转换为处理器指令中的固定工作量。这些为程序员构建更大的软件提供了构建块。因此,在C中,int对象具有固定的大小。分配16字节的内存为几个int对象提供了空间,但它不提供大整数对象。

int的大小通常为4字节(32位(。并且,从-2147483648到2147483647,可能需要2^32个不同的状态。因此,当您尝试存储此*dyn = 9999999999;时,会发生整数溢出。它不是指向内存位置,而是指向该变量的值。

为什么我不能使用整个内存块来存储单个值?

因为int的大小几乎肯定不是16字节,并且当您在*dyn = 9999999999;表达式中取消引用int指针时,该访问被限制为int的大小,可能是2^31-1。

请注意,整数常量9999999999也有一个类型,该类型由编译器根据数字的大小动态确定。在这种情况下,很可能是long long。因此,这里的实际错误是您尝试执行int x = 9999999999;,这与malloc或指针无关。这是一个简单的溢出。

要使用大于21.4亿的数字,必须使用64位类型。使用stdint.h 中的int64_t/uint64_t

不能在其中分配16个字节的memcpysom值,然后通过指向某个任意整数类型的指针访问数据。这是因为有些功能失调的C型系统。简化的解释:malloc返回的数据块在内部没有类型,直到您在那里存储了一些东西。然后,它获得存储时使用的类型,所有后续访问也必须使用相同的类型,其他所有操作都会根据"严格别名规则"调用未定义的行为。

dyn是一个整数指针(实际上,指向16字节的int数组的保留内存(。*dyn是一个整数(此int数组中的第一个元素(。类似于阵列:

int dyn[4];
dyn[0]=9999999999;

9999999999分配给int会导致变量溢出,因为int在现代平台上只允许[-2 147 483 648,+2 147 483 647]范围(至少允许[-32767,+32767](。

9999999999或更好地说明为9,999,999,999不在dyn所指向的int的范围内,无论malloc分配了多少内存:

int *dyn = malloc(16);   // `dyn` points to an `int` object, don´t matter 
// if malloc allocates 16 bytes.
*dyn = 9999999999;       // Attempt to assign an out-of-range value to an `int` object.

int类型的对象应由最现代的系统在内存中分配4个字节。

4字节最多可容纳2^(8*4(=2^32=4294967296个值。

现在您有了int的类型,它等效于signed int的类型。

signed int可以存储正数和负数,但由于它可以存储负数和正数,所以它的范围大不相同。

signed int的范围为-2147483648到2147483647,int的范围也是如此。

因此,您不能int对象中保持9999999999,因为int对象可以存储的最大值是2147483647。

如果要在对象中存储9999999999或9999999999的值,请使用例如long long int,但不要使用long int,因为long int可以保存相同范围的intunsigned int:

long long int *dyn = malloc(16);   // `dyn` points to an `long long int` object.
*dyn = 9999999999;  // Fine, because 9999999999 is in the range of an `long long int` object.

相关内容

  • 没有找到相关文章

最新更新