我试图了解当涉及char和string时,这种内存分配方式是如何工作的。
我知道声明的数组的名称就像指向该数组第一个元素的指针一样,但是该数组将存在于内存的 stack 中。
另一方面,当我们想使用内存堆时,我们使用malloc,但是我发现您可以初始化一个char指针并在同一条声明行上为其分配一个字符串,所以我有一些有关此问题的问题:
1)如果我只是初始化一个char指针并为其分配一个字符串,则该信息在哪里?在堆中?在堆栈中?
例如:char *pointer = "Hello world";
2)我尝试使用malloc初始化我的char指针,并在以后使用它为它分配一个字符串,但是我无法编译它,但出现错误,是什么这个逻辑错了吗?这就是我要尝试的事情:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
能否请您帮助我更多地了解指针和内存分配?非常感谢你! :)
答案 0 :(得分:1)
长问题,但答案很简单。首先,您需要了解什么是指针。
componentDidMount() {
var headers = {
"Content-Type": "application/json",
Authorization: `Token ${authToken}`
};
axios
.get(`${serverURL}users/${this.props.match.params.id}`, {
headers: headers
})
.then(res => {
//console.log(res.data);
let userdetails = res.data;
this.setState({
first_name: userdetails.first_name,
last_name: userdetails.last_name,
email: userdetails.email,
});
})
.catch(function(error) {
console.log(error);
});
}
在这里,您尝试为char分配一个指针。如果您删除*,则会将指针分配给 *pointer = "Hello world";
的字符串文字。
除非您使Assign运算符过载,否则它将不会将其复制到分配的内存中。当您为指针分配新值时,malloc毫无意义,而由malloc分配的内存将丢失
您需要代替它
这些信息住在哪里?
取决于实现的字符串文字的存储位置。它可以在任何地方。请记住,您不能修改字符串文字。尝试这样做是未定义的行为
答案 1 :(得分:1)
1)如果我只是初始化一个char指针并为其分配一个字符串,则该信息在哪里?在堆中?在堆栈中?例如:char * pointer =“ Hello world”;
字符串文字"Hello world"
具有静态存储持续时间。这意味着只要程序正在运行,它就存在于程序可访问的内存中。
确切的位置是特定于实现的。
2)我尝试使用malloc初始化我的char指针,并在以后使用它为它分配一个字符串,但是我无法编译它,但出现错误,此逻辑有什么问题?这就是我想要做的:
char *pointer = malloc(sizeof(char) * 12); *pointer = "Hello world";
这不起作用,因为*pointer
是动态分配的内存中的第一个char
(由malloc()
返回)。字符串文字"Hello world"
表示为字符数组。字符数组不能存储在单个char
中。
在这种情况下,您实际需要做的是将数据从字符串文字复制到动态分配的内存中。
char *pointer = malloc(sizeof(char) * 12);
strcpy(pointer, "Hello world"); /* strcpy() is declared in standard header <string.h> *
请注意,这不会更改表示字符串文字的数据。它将字符串文字中的数据复制到pointer
指向的内存中(并由malloc()
动态分配)。
如果您确实希望pointer
指向字符串文字的(第一个字符),请执行
const char *pointer = "Hello world";
const
代表了一个事实,即修改字符串文字会产生未定义的行为(并且意味着以上内容阻止了使用pointer
来修改该字符串文字)。
如果您想编写非常糟糕的代码,也可以这样做
char *pointer = "Hello world"; /* Danger Will Robinson !!!! */
或(相同的净效果)
char *pointer;
pointer = "Hello world"; /* Danger Will Robinson !!!! */
此pointer
现在可用于修改字符串文字的内容-但这会导致未定义的行为。大多数编译器(如果配置正确)都会对此发出警告-这是您不应执行此操作的许多提示之一。
答案 2 :(得分:1)
1)如果我只是初始化一个char指针并为其分配一个字符串, 这些信息住在哪里?在堆里?在堆栈中?例如:
char *pointer = "Hello world";
无论是在堆栈上还是在堆上。 "Hello world"
是一个字符串文字,通常在可执行文件的rodata
(只读数据)段中创建。实际上,除非您另外指定,否则编译器可以自由地仅存储"Hello world"
的单个副本,即使您将其分配给多个指针也是如此。尽管通常不能将字符串分配给指针,但是由于这是 string文字,因此实际上是为文字本身分配地址-这是唯一起作用的原因。否则,如P__J__所述,您必须将字符串从一个位置复制到另一位置。
2)我尝试使用
malloc
初始化我的char指针并使用它 后来给它分配了一个字符串,但我无法编译它,但出现错误, 此逻辑有什么问题?这就是我要尝试做的事情:char *pointer = malloc(sizeof(char) * 12); *pointer = "Hello world";
您在这里混合苹果和橙子。 char *pointer = malloc (12);
为12个字符(字节)分配存储空间,然后将该新存储块的起始地址分配为pointer
作为其值。 (请记住,指针只是将地址保留为其他值的普通变量)
对于每个分配,都必须有 验证 ,该调用成功,否则您将需要处理失败。分配可以并且确实会失败,并且当分配失败时,malloc, calloc * realloc
都将返回NULL
。因此,每次分配时,您
char *pointer = malloc(12); /* note: sizeof (char) is always 1 */
if (pointer == NULL) { /* you VALIDATE each allocation */
perror ("malloc-pointer");
return 1;
}
继续上述情况,您已分配12字节并将新存储块的起始地址分配给pointer
。然后,您莫名其妙地取消引用pointer
(例如,*pointer
现在具有类型char
),并尝试将字符串文字的地址分配为该字符。 / p>
*pointer = "Hello world"; /* (invalid conversion between pointer and `char`) */
您要执行的操作是将"Hello world"
复制到指针保存的新内存块中。为此,由于您已经知道"Hello world"
是12个字符(包括 nul-termination 字符),因此您可以简单地:
memcpy (pointer, "Hello world", 12);
(注意:,如果您已经有长度,则无需调用strcpy
并使其再次扫描字符串末尾)
现在,新分配的内存块包含"Hello world"
,并且该内存是可变的,因此您可以更改任何喜欢的字符。
由于已分配存储空间,因此free (pointer);
由您决定,该存储空间不再使用。
仔细检查一下,如果还有其他问题,请告诉我。
答案 3 :(得分:1)
我知道声明的数组的名称就像是指向数组第一个元素的指针,…
这是不正确的。数组在许多表达式中的行为与指针类似(因为它会自动转换),但它的表现与第一个元素的指针不同。当用作sizeof
或一元&
的操作数时,数组将是一个数组;它不会转换为指针。另外,不能像指针一样分配数组。您不能为数组分配值。
…但是该数组将存在于内存堆栈中。
数组的存储取决于其定义。如果在任何函数之外定义对象,则该对象具有静态存储持续时间,这意味着该对象存在于整个程序执行过程中。如果在没有_Thread_local
或static
的函数中定义它具有自动存储持续时间,则意味着它存在直到其相关代码块的执行结束为止。 C实现绝大多数将堆栈用于具有自动存储期限的对象(忽略了优化经常不需要使用堆栈这一事实),但是可以选择。
另一方面,当我们想使用内存堆时,我们使用malloc,但是我发现您可以初始化一个char指针并在同一条声明行上为其分配一个字符串,所以我有一些有关此问题的问题:
1)如果我只是初始化一个char指针并为其分配一个字符串,那么此信息在哪里?在堆里?在堆栈中?例如:char * pointer =“ Hello world”;
对于字符串文字"Hello world"
,C实现会创建一个具有静态存储持续时间的字符数组,就像您在文件范围内写入char MyString[12];
或int x;
一样。假设此数组未通过优化消除或更改,则C实现是在内存的某些常规区域中用于程序中内置的数据(可能是“ .rodata”或类似的只读部分)。
然后,对于char *pointer
,C实现创建一个指针。如果此定义出现在函数之外,则它具有静态存储持续时间,并且C实现为此使用一些常规的内存区域。如果它出现在函数内部,则它具有自动存储时间,并且C实现可能为此使用堆栈空间。
然后,对于= "Hello world"
,C实现使用该数组初始化pointer
。为此,它将数组转换为指向其第一个元素的指针,并将该指针用作pointer
的初始值。
2)我尝试使用malloc初始化我的char指针,并在以后使用它为它分配一个字符串,但是我无法编译它,但出现错误,此逻辑有什么问题?这就是我想要做的:
char *pointer = malloc(sizeof(char) * 12);
*pointer = "Hello world";
第二行是错误的,因为*pointer
在声明中的作用与在表达式语句中的作用不同。
在char *pointer = …;
中,*pointer
呈现了应该是char
的“图片”。这就是声明在C中的工作方式。它说*pointer
是char
,因此pointer
是指向char
的指针。但是,要定义和初始化的事物不是*pointer
,而是pointer
。
相反,在*pointer = "Hello world";
中,*pointer
是一个表达式。它使用指针pointer
并将*
运算符应用于它。由于pointer
是指向char
的指针,因此*pointer
是char
。然后*pointer = "Hello world";
尝试将"Hello world"
分配给char
。这是一个错误,因为"Hello world"
不是char
。
您要执行的操作是将指向"Hello world"
的指针分配给pointer
。 (更正确地说,是指向"Hello world"
的第一个字符的指针。)为此,请使用:
pointer = "Hello world";