为什么Malloc并不总是需要指向Char的指针?
以下代码的工作原理:为什么Malloc并不总是需要指向Char的指针?,c,pointers,malloc,C,Pointers,Malloc,以下代码的工作原理: char *p; p="hello"; printf("%s\n",p); 而这一个没有: char *p; strcpy(p,"hello"); printf("%s\n",p); 我知道加上p=malloc(4);在第二个示例中,代码可以正常工作,但这正是我的问题。为什么在第二个示例中需要malloc,而在第一个示例中不需要 我在SO上寻找了类似的问题,但没有人能准确地回答这个问题。“hello”是一个字符串文本,将存在于输出程序中。编译器在编译时在与实际代
char *p;
p="hello";
printf("%s\n",p);
而这一个没有:
char *p;
strcpy(p,"hello");
printf("%s\n",p);
我知道加上p=malloc(4);在第二个示例中,代码可以正常工作,但这正是我的问题。为什么在第二个示例中需要malloc,而在第一个示例中不需要
我在SO上寻找了类似的问题,但没有人能准确地回答这个问题。“hello”
是一个字符串文本,将存在于输出程序中。编译器在编译时在与实际代码相同的位置分配内存*
也就是说,“hello”
的类型将是常量字符[6]
,它将自动转换为字符*
。(使用constchar*
而不是char*
作为字符串文本是一个好习惯)
在第二种情况下,p
在调用strcpy
时是非斜体的,因此结果是未定义的<代码>p=malloc(4)代码>也不足以解决此问题,字符串“hello”由6个字符组成,其中5个字符来自单词hello本身,加上'\0'
以终止字符串
*实际上,在现代系统中,这并不完全正确,它与代码几乎处于同一位置。p=“hello”
将字符串文字“hello”的地址分配给p
,而scanf
需要一个放置扫描输入的位置,因此您需要为其分配一些内存(静态、动态或自动)
要复制字符串literal
hello
,p必须指向一个有效的内存位置,在本例中,该位置不是。p
是一个指针。你需要让它指向一些东西。在第一种情况下
p = "hello";
使p
指向运行时程序内存中某个位置的字符串文字
在第二种情况下,您没有使p
指向任何东西,因此,任何查看p
指向的地方的操作都是无效的
p = malloc(some_size);
使p
指向一段(未初始化的)内存,该内存可以容纳一些大小的字符。如果您保留了足够的空间,那么您可以执行类似于strcpy(p,“hello”)
的操作,因为p
确实指向有效的内存区域,因此可以将其复制到p
所指向的内存中。请注意,某些大小必须至少与要复制到其中的大小相同,包括'\0'
字符串终止符
请注意,这样做:
p = "hello";
strcpy(p, "bye");
将无效,因为“hello”
可以存储在只读内存中,因此您无法覆盖它。因为p
的值将是随机的,任何复制字符串的尝试都将导致崩溃。通过使用malloc,您可以确保p
的值可以进行复制(只要缓冲区足够大)我发现在这种情况下,图片很方便
让我们结合上面的两个片段:
char *p = "Hello";
char *q;
strcpy(q, "goodbye");
printf("p = %s, q = %s\n", p, q);
下面是一个假设的内存映射,显示了p
、q
与字符串“Hello”
和“再见”
之间的关系:
然后我们的内存映射将如下所示:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"Hello" 0x00080000 'H' 'e' 'l' 'l'
0x00080004 'o' 0x00 0x?? 0x??
"goodbye" 0x00080008 'g' 'o' 'o' 'd'
0x0008000C 'b' 'y' 'e' 0x00
...
p 0x01010000 0x00 0x08 0x00 0x00
q 0x01010004 0x40 0x00 0x00 0x00
...
<dynamic> 0x40000000 'g' 'o' 'o' 'd'
0x40000004 'b' 'y' 'e' 0x00
0x40000008 0x?? 0x??
项目地址0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
“你好”0x00080000“H”“e”“l”“l”
0x00080004'o'0x00 0x??0x??
“再见”0x00080008“g”“o”“o”“d”
0x0008000C“b”y“e”0x00
...
p 0x01010000 0x00 0x08 0x00 0x00
q 0x010100004 0x40 0x00 0x00 0x00
...
0x40000000'g'o'o'd'
0x40000004“b”y“e”0x00
0x40000008 0x??0x??
在这种情况下,malloc
留出从0x40000000开始的10字节内存,并将该地址复制到q
。调用strcpy将字符串文本“再见”的内容复制到该位置
1如果
q
已声明为static
或在文件范围内(在任何函数之外),则它将被初始化为0(0x00000000) 你是在5分钟的宽限期内编辑的吗?我发誓它最初说的是scanf
,而不是strcpy
,这在一定程度上改变了答案。是的,我认为strcpy会使问题更容易理解,我认为它不会改变答案。是吗?这是一个基本问题。一点研究应该会很快给你答案。我在SO中查找了类似的内容,但找不到确切的答案。@awoodland在C语言中没有名为strdup的函数,所以我不推荐它。除非您没有其他选择,否则请坚持使用标准函数。但是使用p=“hello”时,字符串文本必须存储在某个位置,因此程序会自动分配/删除该字符串?另外,如果您想使用scanf或strcpy,如何为p分配静态、动态和自动内存?我只知道使用malloc,我认为这是动态分配对吗?@DanielScocco yes字符串文本通常存储在二进制程序文件本身的静态数据部分。动态分配是malloc
,自动内存就在堆栈上,就像charp[size]
其中size
是一个整数,静态内存就是static int代码>。你说“如果你保留了足够的内存,你就可以做strcpy(p,“hello”)”之类的事情。p的4字节内存不足以在那里存储任何字符串吗,因为p始终只是指向第一个字符的指针?@DanielScoccop
指向内存strcpy
正在复制“hello”
。它必须至少有6个字节大(1个用于hello
的每个字符,1个用于空终止符)。它在这里仅分配4个字节。也许这是个幸运的巧合。@Danielscock:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"Hello" 0x00080000 'H' 'e' 'l' 'l'
0x00080004 'o' 0x00 0x?? 0x??
"goodbye" 0x00080008 'g' 'o' 'o' 'd'
0x0008000C 'b' 'y' 'e' 0x00
...
p 0x01010000 0x00 0x08 0x00 0x00
q 0x01010004 0x?? 0x?? 0x?? 0x??
char *p = "Hello";
char *q;
q = malloc(10);
strcpy(q, "goodbye");
printf("p = %s, q = %s\n", p, q);
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"Hello" 0x00080000 'H' 'e' 'l' 'l'
0x00080004 'o' 0x00 0x?? 0x??
"goodbye" 0x00080008 'g' 'o' 'o' 'd'
0x0008000C 'b' 'y' 'e' 0x00
...
p 0x01010000 0x00 0x08 0x00 0x00
q 0x01010004 0x40 0x00 0x00 0x00
...
<dynamic> 0x40000000 'g' 'o' 'o' 'd'
0x40000004 'b' 'y' 'e' 0x00
0x40000008 0x?? 0x??