【发布时间】:2019-08-28 17:31:07
【问题描述】:
我有一个 char 数组,我们知道一个 char 大小是 1 个字节。现在我当然必须收集一些 char -> getchar() 并同时将数组增加 1 个字节(没有 malloc,只有库:stdio.h)
我的建议是,指向数组并以某种方式将该数组增加 1,直到没有更多的字符可以获取,或者你的内存用完了......
【问题讨论】:
我有一个 char 数组,我们知道一个 char 大小是 1 个字节。现在我当然必须收集一些 char -> getchar() 并同时将数组增加 1 个字节(没有 malloc,只有库:stdio.h)
我的建议是,指向数组并以某种方式将该数组增加 1,直到没有更多的字符可以获取,或者你的内存用完了......
【问题讨论】:
【讨论】:
是否可以在使用
char数组时增加它,而不使用malloc?
快速回答:不,如果不重新分配数组,就不可能增加数组的大小。
有趣的回答:不要使用malloc(),使用realloc()。
长答案:
如果char 数组具有静态或自动存储类,则很可能无法在运行时增加其大小,因为将其保持在同一地址会需要将位于更高地址的对象移动或重新分配到其他地方.
如果数组是由malloc 获得的,如果在内存中没有分配其他对象,则可以扩展其大小。事实上realloc() 更大的尺寸可能会返回相同的地址。问题是无法预测,如果 realloc 返回不同的地址,则当前空间已被释放,因此指向它的指针现在无效。
进行这种重新分配的有效方法是几何地增加大小,一次增加一个因子,2x、1.5x、1.625x ...以最小化重新分配的数量并保持线性时间作为数组线性增长。您可以为数组的分配大小和存储到其中的字符数使用不同的变量。
这是一个例子:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *a = NULL;
size_t size = 0;
size_t count = 0;
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (count >= size) {
/* reallocate the buffer to 1.5x size */
size_t newsize = size + size / 2 + 16;
char *new_a = realloc(a, new_size);
if (new_a == NULL) {
fprintf("out of memory for %zu bytes\n", new_size);
free(a);
return 1;
}
a = new_a;
size = new_size;
}
a[count++] = c;
}
for (i = 0; i < count; i++) {
putchar(a[i]);
}
free(a);
return 0;
}
【讨论】:
有两种方法可以在不使用动态内存分配的情况下为字符串创建空间(malloc...)。您可以使用静态数组或具有自动存储持续时间的数组,您需要指定最大数量,您可能永远无法达到。但请始终检查它。
#define BUFFER_SIZE 0x10000
静态
static char buffer[BUFFER_SIZE];
或者自动(需要保证BUFFER_SIZE小于栈大小)
int main() {
char buffer[BUFFER_SIZE];
...
};
操作系统也进行了优化。它可能会延迟分配整个(静态/自动)缓冲区,以便只有使用的部分在物理内存中。 (这也适用于动态内存分配函数。)我发现 calloc (用于大块)只是为程序分配虚拟内存;仅在访问内存页面时(可能通过 cpu 引发的一些中断)才清除内存页面。我将它与 malloc 和 memset 的分配进行了比较。如果程序没有访问缓冲区的所有字节/页面,则 memset 会做不必要的工作。
如果你不能用 malloc... 分配缓冲区,创建一个足够大的静态/自动数组,让操作系统为你分配。它不会占用相同的空间二进制,因为它只是存储为一个大小。
【讨论】: