如何在不浪费 C 语言内存的情况下创建快速且巨大的联合数组?
How to create a fast & huge union array without wasting memory in C?
我想使用 union
在同一内存中存储不同的数据类型。该数组长度固定,访问速度快,内存浪费尽可能小。
我将定义存储相同数据类型的区域。所以我这样做:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#define RESERVED_BYTES 1073741824
//#define RESERVED_BYTES 2147483648
typedef union {
char c[RESERVED_BYTES]; //1Byte
uint8_t u8[RESERVED_BYTES]; //1Byte
uint16_t u16[RESERVED_BYTES / 2]; //2Byte
} array_type;
int main(void)
{
array_type *array;
array = calloc(1, sizeof(array_type));
getchar();
return 0;
}
这段代码有效并分配了 1GB 的内存,并且该数组的元素可以与 array[0].u8[3]
一起使用,例如我知道我必须处理索引,因为它们取决于字节大小。
遗憾的是,如果我增加内存大小(请参阅 #define RESERVED_BYTES 2147483648
)并且在 64 位计算机上使用 MSVS 2013,我会收到 error C2148: total size of array must not exceed 0x7fffffff bytes
代码无法编译。另一方面,像 array = calloc(2147483648, sizeof(*array));
.
这样直接将 2GB 放入 calloc
是没有问题的
但是这个版本我可能会浪费内存:
union {
char c; //1Byte
uint8_t u8; //1Byte
uint16_t u16; //2Byte
} *array;
或者需要构建一个耗时的函数来计算我想避免的两个索引:
union {
char c[2]; //1Byte
uint8_t u8[2]; //1Byte
uint16_t u16[1]; //2Byte
} *array;
array[3].u8[2] = 1;
那么如何处理这个问题呢?
I'd like to store different datatypes in the same memory using union. This array has a fixed length
根据您发布的代码,数组具有相同的 字节 长度,但根据它们的不同 不同 个元素类型。
I receive an error C2148: total size of array must not exceed 0x7fffffff bytes.
如果我猜的话,这可能与甚至适用于 64 位编译的 static 数据的 2 GB 限制有关,这意味着 array_type
永远无法实例化为 global/static 变量或 local/stack 变量 (Memory Limits for Applications on Windows)。最后,这意味着剩下的唯一选择就是在堆上动态分配这样一个数组。
But with this version I might waste memory
...or need to build a time-consuming function that calculates the both indices
您可以通过稍微修改 union
定义来实现(几乎)相同的效果,而不会浪费内存,也不需要额外的访问器。
#define RESERVED_BYTES 2147483648
typedef union {
void *pv;
char *pc;
uint8_t *pu8;
uint16_t *pu16;
} parray_type;
int main(void)
{
parray_type parray;
parray.pv = calloc(RESERVED_BYTES, 1);
// last element in allocated buffer for each type
char c = parray.pc[RESERVED_BYTES - 1];
uint8_t u8 = parray.pu8[RESERVED_BYTES - 1];
uint16_t u16 = parray.pu16[RESERVED_BYTES / 2 - 1];
return 0;
}
当然,您必须始终记住 pu16
的最大索引是 pc
和 pu8
的一半,但这也是原始代码中的前提.
我想使用 union
在同一内存中存储不同的数据类型。该数组长度固定,访问速度快,内存浪费尽可能小。
我将定义存储相同数据类型的区域。所以我这样做:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#define RESERVED_BYTES 1073741824
//#define RESERVED_BYTES 2147483648
typedef union {
char c[RESERVED_BYTES]; //1Byte
uint8_t u8[RESERVED_BYTES]; //1Byte
uint16_t u16[RESERVED_BYTES / 2]; //2Byte
} array_type;
int main(void)
{
array_type *array;
array = calloc(1, sizeof(array_type));
getchar();
return 0;
}
这段代码有效并分配了 1GB 的内存,并且该数组的元素可以与 array[0].u8[3]
一起使用,例如我知道我必须处理索引,因为它们取决于字节大小。
遗憾的是,如果我增加内存大小(请参阅 #define RESERVED_BYTES 2147483648
)并且在 64 位计算机上使用 MSVS 2013,我会收到 error C2148: total size of array must not exceed 0x7fffffff bytes
代码无法编译。另一方面,像 array = calloc(2147483648, sizeof(*array));
.
calloc
是没有问题的
但是这个版本我可能会浪费内存:
union {
char c; //1Byte
uint8_t u8; //1Byte
uint16_t u16; //2Byte
} *array;
或者需要构建一个耗时的函数来计算我想避免的两个索引:
union {
char c[2]; //1Byte
uint8_t u8[2]; //1Byte
uint16_t u16[1]; //2Byte
} *array;
array[3].u8[2] = 1;
那么如何处理这个问题呢?
I'd like to store different datatypes in the same memory using union. This array has a fixed length
根据您发布的代码,数组具有相同的 字节 长度,但根据它们的不同 不同 个元素类型。
I receive an error C2148: total size of array must not exceed 0x7fffffff bytes.
如果我猜的话,这可能与甚至适用于 64 位编译的 static 数据的 2 GB 限制有关,这意味着 array_type
永远无法实例化为 global/static 变量或 local/stack 变量 (Memory Limits for Applications on Windows)。最后,这意味着剩下的唯一选择就是在堆上动态分配这样一个数组。
But with this version I might waste memory
...or need to build a time-consuming function that calculates the both indices
您可以通过稍微修改 union
定义来实现(几乎)相同的效果,而不会浪费内存,也不需要额外的访问器。
#define RESERVED_BYTES 2147483648
typedef union {
void *pv;
char *pc;
uint8_t *pu8;
uint16_t *pu16;
} parray_type;
int main(void)
{
parray_type parray;
parray.pv = calloc(RESERVED_BYTES, 1);
// last element in allocated buffer for each type
char c = parray.pc[RESERVED_BYTES - 1];
uint8_t u8 = parray.pu8[RESERVED_BYTES - 1];
uint16_t u16 = parray.pu16[RESERVED_BYTES / 2 - 1];
return 0;
}
当然,您必须始终记住 pu16
的最大索引是 pc
和 pu8
的一半,但这也是原始代码中的前提.