关于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); } 

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

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

另外,这些行:

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

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

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

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

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

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

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

 #include  /* for strdup, strlen */ #include  /* 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.

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

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

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

要解决你的第二个问题,通过执行语句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); 

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 
  • sizeof()返回指针的大小,而不是返回分配的字节数。 您不需要计算分配的字节数,只需检查返回的指针是否为NULL
  • copy = '\0' ; 重置指针并使其为NULL

您可以使用:

size_t malloc_usable_size(void * ptr);

而不是:sizeof

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