【发布时间】:2020-04-13 15:33:11
【问题描述】:
目前正在学习 C 中的内存管理,并且我目前遇到了随着循环迭代而增加字符串长度的问题。
我试图找出逻辑上的方法是这样的:
// return string with "X" removed
char * notX(char * string){
result = "";
if(for int = 0; i < strlen(string); i++){
if (string[i] != 'X') {
result += string[i];
}
}
return result;
}
在其他语言中足够简单,但在 C 中管理内存却有点挑战性。我遇到的困难是当我使用 malloc 和 realloc 来初始化和更改字符串的大小时。在我目前尝试的代码中:
char * notX(char * string){
char* res = malloc(sizeof(char*)); // allocate memory for string of size 1;
res = ""; // attempted to initialize the string. Fairly certain this is incorrect
char tmp[2]; // temporary string to hold value to be concatenated
if(for int = 0; i < strlen(string); i++){
if (string[i] != 'X') {
res = realloc(res, sizeof(res) + sizeof(char*)); // reallocate res and increasing its size by 1 character
tmp[0] = string[i];
tmp[1] = '\0';
strcat(res, tmp);
}
}
return result;
}
注意,我发现成功初始化结果是一些大数组,例如:
char res[100];
但是,我想了解如何在不初始化具有固定大小的数组的情况下解决此问题,因为这可能会浪费内存空间或内存不足。
【问题讨论】:
-
malloc(sizeof(char*))= 分配指针的大小。此外,realloc(res, sizeof(res) + sizeof(char*));重新分配到 两个 指针总是 的大小。我认为您不了解sizeof的工作原理。而res = "";造成了两场灾难。 (1) 它泄露了前一行分配的内存,(2) 它现在导致res指向一个常量字符串,即内存不再动态管理,因此将它传递给realloc调用未定义的行为. -
您的结果字符串永远不会大于原始字符串,因此您可以从分配
len +1字符开始。在循环结束时,您可以决定重新分配()它。 -
其他问题包括每次迭代都重新计算
strlen(string),即使它是恒定的。照原样,您甚至不需要知道长度,因为您可以迭代直到遇到 NUL 终止符。同样重复的strcat变得越来越无效,因为它每次都需要找到字符串的结尾。而是跟踪结束位置并附加到那里。 (注意这些都是比较长远的事情要考虑和一般的思考方式,先了解一下内存分配、指针和sizeof是怎么工作的,还有数组和指针的区别。)