为什么我执行此代码时:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
size_t size = 4;
char *str = malloc(size);
str = "hello";
printf("malloc %s: %d\n", str, size);
printf("strlen %s: %d\n", str, strlen(str));
printf("sizeof %s: %d\n", str, sizeof("hello"));
return 0;
}
我获得以下内容:
malloc hello: 4
strlen hello: 5
sizeof hello: 6
基本上,我只需要知道为什么如果我只分配4个字节,我可以存储一个字符串,其中包含5个大小为6个字节的字符?
答案 0 :(得分:1)
使用您的行str = "hello"
,您将指针重新指定为指向内存中创建"hello"
的位置。你在这里做的是你的malloc
内存泄漏很小,因为你不再引用所请求的堆空间。
答案 1 :(得分:0)
str = "hello"
只需重新指定指针;它不会在您刚分配的内存中存储任何内容。你刚刚创建了内存泄漏!
要复制字符串内容本身,您应该使用strncpy()
。
答案 2 :(得分:0)
此行str = "hello";
将指针设置为指向其他位置。 (如果您尝试执行sizeof(str)
,最终会得到值4
,这是指针的大小。)
strlen(str)
生成不带空字符的字符串长度,这就是5
的原因。
sizeof("hello")
计算存储"hello"
所需的内存,因此它也考虑了空字符,这就是输出为6
的原因。所以基本上你的字符串有6个字符。
答案 3 :(得分:0)
Q1。 为什么我在字符串缓冲区中获得不同的大小?
三个输出:
size_t
是您系统中的四个字节。这就是sizeof(size)
为4,但不的原因,因为作业size = 4
。当然,你的printf尺寸值也是4. strlen(str)
为您提供字符串"hello"
的长度,由5个字符组成。 (字符串长度不包括\0
nul char)。 C中的字符串是char[N]
(数组)类型。在第3个pritnf中,sizeof("hello")
的值为6
,因为"hello"
字符串是6个字符长数组(包括字符串终止\0
nul,hello的类型是char[6]
)。
在内存"hello"
中,字符串存储在图表中,如下所示:
str 23 24 25 26 27 28
+----+ +----+----+----+----+----+----+
| 23 | | h | e | l | l | o | \0 |
+----+ +----+----+----+----+----+----+
Address of hello string is first address = 23
str: is pointer, used to store address of hello string
赋值str = "hello";
,基本上将字符串hello的地址存储到指针变量str
,如上图所示。
Q2。 为什么我只分配4个字节,我可以存储一个字符串,其中包含5个大小为6字节的字符
错了,实际上你并没有将“hello”字符串复制到动态分配的空间中。最初str
包含malloc()
返回的地址。但是由于赋值语句str = "hello";
,您在赋值语句中用常量字符串文字“hello”覆盖了已分配内存的内存地址。
要理解这一点,您可以执行一个示例:
#include<stdio.h>
int main(){
size_t size = 6;
char *str = malloc(size);
printf("\n malloc str: %p", str);
str = "hello";
printf("\n hello str: %p", str);
return 1;
}
输出:
malloc str: 0x804a078
hello str: 0x8048609 // allocated address lost
Codepade link
(旁注:你永远不应该丢失动态(显式)分配内存的地址,因为当你使用free()显式释放它时需要它。)
如果要复制到已分配的空间,可以通过访问/索引每个内存位置来分配(1),或者(2)使用库函数strcpy()
。
例如尝试:
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0'; // nul termination is important
or
strcpy(str, "abc"); // strcpy add nul itself
但是你无法复制"hello"
字符串,因为str
没有分配足够的空间来容纳完整的字符串,这样做会导致buffer-overrun问题,即C {/ 3}} C ++在运行时。