为什么不能在动态分配的内存块中存储一个非常大的单个值?
Why can't you store an extremely large single value in a dynamically allocated block of memory?
为什么我不能在这个分配的内存块中存储大整数?
int *dyn = malloc(16);
*dyn = 9999999999;
printf("%lli\n", *dyn);
free(dyn);
在编译时,GCC 警告我将发生整数溢出。果然,打印出来的时候,已经溢出了
为什么我不能使用整个内存块来存储单个值?
dyn
是一个整型指针(实际上是指向一个16字节的int数组的预留内存)。 *dyn
是一个整数(此 int 数组的第一个元素)。类似于数组:
int dyn[4];
dyn[0]=9999999999;
将 9999999999
赋值给 int
会导致变量溢出,因为 int
在现代平台上只允许 [−2 147 483 648, +2 147 483 647] 范围(和至少 [−32767, +32767]).
int的大小通常为4字节(32位)。而且,它可以采用 2^32 个不同的状态,从 -2147483648 到 2147483647。
因此,当您尝试存储此 *dyn = 9999999999;
时,会发生整数溢出。
它不是指向内存位置,而是指向该变量的值。
*dyn = 9999999999;
不会指示计算机使用分配给 dyn
的所有内存来存储值 9999999999。
在 C 中,dyn
有一个类型。类型是“指向 int
的指针”。然后 *dyn
具有类型 int
,它具有特定的固定位数。它没有表示“为 dyn
”分配的所有内存的类型。
由于 *dyn
是一个 int
,*dyn = 9999999999;
告诉计算机将 9999999999 放入 int
。由于 9999999999 对于 C 实现中的 int
来说太大了,因此会发生溢出。
我们可以对计算机进行编程并设计编程语言来管理任意大小的整数。一些语言,例如 Python,就是这样做的。然而,这需要额外的软件,特别是当程序 运行 时必须做一些可变工作量的软件,以便处理出现的任何大小的数字。 C被设计成一种基本语言。它适用于特定大小的对象,并且通常将 C 代码转换为处理器指令中固定数量的工作。这些为程序员构建更大的软件提供了构建块。因此,在 C 中,int
对象具有固定大小。分配 16 字节的内存可为多个 int
对象提供 space,但不提供大整数对象。
Why can't I use the entire block of memory to store a single value?
因为 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 个字节,memcpy
som 值在那里,然后通过指向某个任意整数类型的指针访问数据。这是因为 C 类型系统有些功能失调。简单解释:从 malloc 返回的数据块在内部没有类型,直到你在那里存储一些东西。然后它获取您在存储时使用的类型,并且所有后续访问也必须使用相同的类型,其他所有内容都会根据 "the strict aliasing rule".
调用未定义的行为
9999999999
或更好地说明 9,999,999,999
不在 int
的范围内,dyn
指向该范围,无论内存有多大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 = 4,294,967,296 个值。
现在你有了 int
的类型,它等同于 signed int
的类型。
signed int
可以存储正数和负数,但是由于它可以存储正数和负数,所以它的范围很不一样。
signed int
的范围是 -2,147,483,648 到 2,147,483,647,int
.
的范围也是如此
所以你不能在int
对象中保存9,999,999,999,因为int
对象可以存储的最大值是2,147,483,647。
如果要在对象中存储 9,999,999,999 或 9999999999
的值,请使用 f.e。 long long int
,但不是 long int
,因为 long int
可以包含 int
和 unsigned 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.
为什么我不能在这个分配的内存块中存储大整数?
int *dyn = malloc(16);
*dyn = 9999999999;
printf("%lli\n", *dyn);
free(dyn);
在编译时,GCC 警告我将发生整数溢出。果然,打印出来的时候,已经溢出了
为什么我不能使用整个内存块来存储单个值?
dyn
是一个整型指针(实际上是指向一个16字节的int数组的预留内存)。 *dyn
是一个整数(此 int 数组的第一个元素)。类似于数组:
int dyn[4];
dyn[0]=9999999999;
将 9999999999
赋值给 int
会导致变量溢出,因为 int
在现代平台上只允许 [−2 147 483 648, +2 147 483 647] 范围(和至少 [−32767, +32767]).
int的大小通常为4字节(32位)。而且,它可以采用 2^32 个不同的状态,从 -2147483648 到 2147483647。
因此,当您尝试存储此 *dyn = 9999999999;
时,会发生整数溢出。
它不是指向内存位置,而是指向该变量的值。
*dyn = 9999999999;
不会指示计算机使用分配给 dyn
的所有内存来存储值 9999999999。
在 C 中,dyn
有一个类型。类型是“指向 int
的指针”。然后 *dyn
具有类型 int
,它具有特定的固定位数。它没有表示“为 dyn
”分配的所有内存的类型。
由于 *dyn
是一个 int
,*dyn = 9999999999;
告诉计算机将 9999999999 放入 int
。由于 9999999999 对于 C 实现中的 int
来说太大了,因此会发生溢出。
我们可以对计算机进行编程并设计编程语言来管理任意大小的整数。一些语言,例如 Python,就是这样做的。然而,这需要额外的软件,特别是当程序 运行 时必须做一些可变工作量的软件,以便处理出现的任何大小的数字。 C被设计成一种基本语言。它适用于特定大小的对象,并且通常将 C 代码转换为处理器指令中固定数量的工作。这些为程序员构建更大的软件提供了构建块。因此,在 C 中,int
对象具有固定大小。分配 16 字节的内存可为多个 int
对象提供 space,但不提供大整数对象。
Why can't I use the entire block of memory to store a single value?
因为 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 个字节,memcpy
som 值在那里,然后通过指向某个任意整数类型的指针访问数据。这是因为 C 类型系统有些功能失调。简单解释:从 malloc 返回的数据块在内部没有类型,直到你在那里存储一些东西。然后它获取您在存储时使用的类型,并且所有后续访问也必须使用相同的类型,其他所有内容都会根据 "the strict aliasing rule".
9999999999
或更好地说明 9,999,999,999
不在 int
的范围内,dyn
指向该范围,无论内存有多大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 = 4,294,967,296 个值。
现在你有了 int
的类型,它等同于 signed int
的类型。
signed int
可以存储正数和负数,但是由于它可以存储正数和负数,所以它的范围很不一样。
signed int
的范围是 -2,147,483,648 到 2,147,483,647,int
.
所以你不能在int
对象中保存9,999,999,999,因为int
对象可以存储的最大值是2,147,483,647。
如果要在对象中存储 9,999,999,999 或 9999999999
的值,请使用 f.e。 long long int
,但不是 long int
,因为 long int
可以包含 int
和 unsigned 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.