关于malloc和sizeof的新手问题

时间:2009-10-07 19:00:00

标签: c malloc sizeof

有人可以向我解释为什么我对字符串大小为6的malloc的调用返回4字节的sizeof?事实上,我给malloc的任何整数参数我得到sizeof为4.接下来,我试图复制两个字符串。为什么我复制的字符串输出(NULL)? 以下是我的代码:

int main()
{
    char * str = "string";
    char * copy = malloc(sizeof(str) + 1);
    printf("bytes allocated for copy: %d\n", sizeof(copy));
    while(*str != '\0'){
        *copy = *str;
        str++;
        copy++;
    }
    copy = '\0';
    printf("%s\n", copy);
}

8 个答案:

答案 0 :(得分:17)

sizeof(str)返回类型为char*的指针的大小。你应该做的是malloc自己的字符串大小:

char * copy = malloc(strlen(str) + 1);

另外,这些行:

while(*str != '\0'){
        *copy = *str;
        str++;
        copy++;
}
copy = '\0';

可以像这样轻松地在C中重写:

while(*copy++ = *str++);

答案 1 :(得分:4)

首先你应该明白 sizeof (xxx)其中xxx是任何左值表达式(变量)总是等同于 sizeof xxx的类型) )。因此,你的 sizeof (str)真正做的是返回char *的大小,即任何其他指针的大小。在32位架构上,你将得到4,在64位架构上,它将是8,等等。

所以,正如其他人也解释过你必须知道你要分配的字符串的长度,然后加1来存储终端\ 0,C隐含地用来放在字符串的末尾。

但是要做你想做的事情(复制一个字符串并分配必要的空间),使用 strdup 会更简单,更有效,这正是如此: malloc strcopy

您也不应忘记释放自己分配的空间(使用malloc,calloc,strdup或任何其他分配功能)。在C中,当分配的变量超出范围时,它不会消失。它将一直使用到程序结束。这就是你所谓的内存泄漏。

#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */

int main()
{
    char * str = "string";
    char * copy = strdup(str);
    printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
    printf("%s\n", copy);
    free(copy);
}

最后一点:我将消息更改为字节至少已分配,因为您在调用malloc时并不真正知道分配的大小。它经常分配一个比你要求的更多的空间。一个原因是在许多内存管理器中,使用一些隐藏数据结构将空闲块链接在一起,并且任何分配的块应该能够包含至少这样的结构,另一个原因是分配的块总是以这样的方式对齐以便与任何类型兼容对准。

希望它能帮助你更好地理解C.

答案 2 :(得分:3)

你得到了str 指针的大小(4个字节),而不是它指向的是什么?

答案 3 :(得分:2)

sizeof(str)返回将指针存储到字符串所需的空间,而不是字符串本身。例如,您可以使用strlen(str)查看字符串的大小。

然后你会影响你的copy指向一个值为0的整数(字符'\0')。它与copy = NULL相同,这是printf()函数向您显示的内容。

答案 4 :(得分:1)

要解决第二个问题,通过执行语句copy++,您已更改copy的值(即内存中包含char数组的地址),以便通过打印出来的时间,它指向数组的末尾而不是开头(malloc()返回的值)。你需要一个额外的变量来更新字符串能够访问字符串的开头:

修改以修复malloc/sizeof问题 - 感谢CL。

char * str = "string";
/*   char * copy = malloc(sizeof(str) + 1);  Oops  */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
    *copy = *str;
    str++;
    copy++;
}
copy = '\0';
printf("%s\n", original_copy);

答案 5 :(得分:1)

sizeof()返回变量实际类型的大小。因此,当您将类型定义为char *时,它将返回指针的大小。

但是如果你把你的变量变成一个数组,那么sizeof会返回数组本身的大小,这可以做你想做的事情:

char *ptr = "moo to you";
char arr[] = "moo to you";

assert(sizeof(ptr) == 4);   // assuming 32 bit
assert(sizeof(arr) == 11);  // sizeof array includes terminating NUL
assert(strlen(arr) == 10);  // strlen does not include terminating NUL

答案 6 :(得分:1)

  • sizeof()返回指针的大小,而不是返回的已分配字节数。您不需要计算分配的字节数,只需检查返回的指针是否不是NULL
  • copy = '\0'行;重置指针并使其成为NULL

答案 7 :(得分:0)

您可以使用:

size_t malloc_usable_size(void * ptr);

而不是:sizeof

但它返回分配的内存块的实际大小!不是你传给malloc的大小!