Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Malloc并不总是需要指向Char的指针?_C_Pointers_Malloc - Fatal编程技术网

为什么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始终只是指向第一个字符的指针?@DanielScocco
p
指向内存
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??