Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.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
C 指向字符串的指针意外更改了其值_C_Arrays_String_Pointers_Malloc - Fatal编程技术网

C 指向字符串的指针意外更改了其值

C 指向字符串的指针意外更改了其值,c,arrays,string,pointers,malloc,C,Arrays,String,Pointers,Malloc,我注意到,在使用malloc分配的数组中写入字符串时,其值会发生变化。为了清楚起见,下面是复制此错误的代码: #include <unistd.h> #include <string.h> #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #define N (20) int main() { char * a_p; a_p = malloc( N * s

我注意到,在使用malloc分配的数组中写入字符串时,其值会发生变化。为了清楚起见,下面是复制此错误的代码:

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>

#define N (20)

int main()
{
   char * a_p;
   a_p = malloc( N * sizeof(char));
   printf(" * 01 pointer -> %p\n", a_p);
   a_p = "something";
   printf(" * 02 pointer -> %p\n", a_p);
   printf("-- TEST --\n");
   return 0;

}

而我期望相同的值,因为我不会改变指针指向的位置,至少不会直接指向。这会导致使用免费软件时出现问题。树林下面发生了什么?我错过了什么?如何以正确的方式做这些事情

文本字符串基本上是数组,当您将其分配给a_p时,它会退化为指向第一个元素的指针。那个地址正在打印中

而且,由于您没有保留分配内存的地址,因此内存泄漏

此外,您不能免费使用它,这就足以说明它不是动态分配的。从标准

free函数使ptr指向的空间 已解除分配,即可供进一步分配。如果ptr是 如果指针为空,则不会发生任何操作。否则,如果参数没有 匹配内存管理函数先前返回的指针,或 如果通过调用free或realloc释放了空间,则 行为是未定义的

这就解释了为什么在试图释放尚未分配的内存时会遇到问题

同样,要实现类似复制的功能,需要使用strcpy、strncpy或strdupPOSIX兼容

有关更多信息,请查看此。标准明确说明了如何在转换步骤中将其视为数组

特别是这个部分衰减的指针是char*类型,这就是为什么

对于字符串文字,数组元素的类型为 字符,并用多字节的单个字节初始化 字符序列


文本字符串基本上是数组,当您将其分配给a_p时,它会退化为指向第一个元素的指针。那个地址正在打印中

而且,由于您没有保留分配内存的地址,因此内存泄漏

此外,您不能免费使用它,这就足以说明它不是动态分配的。从标准

free函数使ptr指向的空间 已解除分配,即可供进一步分配。如果ptr是 如果指针为空,则不会发生任何操作。否则,如果参数没有 匹配内存管理函数先前返回的指针,或 如果通过调用free或realloc释放了空间,则 行为是未定义的

这就解释了为什么在试图释放尚未分配的内存时会遇到问题

同样,要实现类似复制的功能,需要使用strcpy、strncpy或strdupPOSIX兼容

有关更多信息,请查看此。标准明确说明了如何在转换步骤中将其视为数组

特别是这个部分衰减的指针是char*类型,这就是为什么

对于字符串文字,数组元素的类型为 字符,并用多字节的单个字节初始化 字符序列


您正在直接更改指针。此声明

a_p = "something";
a_p = "something";
if ( p1 == p2 )
相当于

a_p = &"something"[0];
字符串文字具有字符数组的类型。例如,字符串literal something的类型为char[10]

来自C标准6.4.5字符串文本

6在翻译阶段7中,将值为零的字节或代码附加到 由字符串文字产生的每个多字节字符序列 或文字。78然后使用多字节字符序列 仅初始化静态存储的持续时间和长度数组 足以容纳序列的。对于字符串文字, 数组元素的类型为char,并使用 多字节字符序列的单个字节

在表达式中使用。极少数例外情况下,数组被转换为指向其第一个元素的指针

来自C标准6.3.2.1左值、数组和函数指示符

3除非它是sizeof运算符或一元数的操作数& 运算符,或是用于初始化数组的字符串文字 类型为“”的数组“”的表达式转换为 类型为“指向类型的指针”且指向初始值的表达式 数组对象的元素,并且不是左值。如果数组对象 已注册存储类,行为未定义

那么在这个声明之后,

a_p = "something";
a_p = "something";
if ( p1 == p2 )
指针指向具有静态存储持续时间的字符串文字的第一个字符

我想你是说

strcpy( a_p, "something" );
也就是说,您希望在动态分配的内存中复制字符串文字

要考虑到,即使您要编写以下代码

char *p1 = "string";
char *p2 = "string";
因此,p1不必等于p2,因为编译器可以根据编译器选项将这两个相同的字符串文本放在不同的内存范围中

那么if语句呢

a_p = "something";
a_p = "something";
if ( p1 == p2 )
可以生成true或false。

您正在更改 直接指向指针。此声明

a_p = "something";
a_p = "something";
if ( p1 == p2 )
相当于

a_p = &"something"[0];
字符串文字具有字符数组的类型。例如,字符串literal something的类型为char[10]

来自C标准6.4.5字符串文本

6在翻译阶段7中,将值为零的字节或代码附加到 由字符串文字产生的每个多字节字符序列 或文字。78然后使用多字节字符序列 仅初始化静态存储的持续时间和长度数组 足以容纳序列的。对于字符串文字, 数组元素的类型为char,并使用 多字节字符序列的单个字节

在表达式中使用。极少数例外情况下,数组被转换为指向其第一个元素的指针

来自C标准6.3.2.1左值、数组和函数指示符

3除非它是sizeof运算符或一元数的操作数& 运算符,或是用于初始化数组的字符串文字 类型为“”的数组“”的表达式转换为 类型为“指向类型的指针”且指向初始值的表达式 数组对象的元素,并且不是左值。如果数组对象 已注册存储类,行为未定义

那么在这个声明之后,

a_p = "something";
a_p = "something";
if ( p1 == p2 )
指针指向具有静态存储持续时间的字符串文字的第一个字符

我想你是说

strcpy( a_p, "something" );
也就是说,您希望在动态分配的内存中复制字符串文字

要考虑到,即使您要编写以下代码

char *p1 = "string";
char *p2 = "string";
因此,p1不必等于p2,因为编译器可以根据编译器选项将这两个相同的字符串文本放在不同的内存范围中

那么if语句呢

a_p = "something";
a_p = "something";
if ( p1 == p2 )
可以产生true或false。

字符串literal something表示一系列以null结尾的字符,这些字符很可能位于某个只读区域。如果在GNU/Linux系统上构建/link/run,则为text

最初,p指向内存区域中malloc正在分配缓冲区的某个地方。您可以自由写入a_p指向的位置,释放它,等等。当您执行赋值a_p=something;,您并不是将字符写入p所指向的位置,而是将该指针更改为指向该字符串的开头。现在,您将指向malloc未分配的只读内存,因此其相应的空闲函数无法执行任何有意义的操作

为了安全起见,请使用strcpy或更好的方法,使用strncpy将字符复制到目标a_p。

字符串literal something表示最有可能位于某个只读区域的以null结尾的字符系列。如果在GNU/Linux系统上构建/link/运行,请使用文本

最初,p指向内存区域中malloc正在分配缓冲区的某个地方。您可以自由写入a_p指向的位置,释放它,等等。当您执行赋值a_p=something;,您并不是将字符写入p所指向的位置,而是将该指针更改为指向该字符串的开头。现在,您将指向malloc未分配的只读内存,因此其相应的空闲函数无法执行任何有意义的操作

为了安全起见,请使用strcpy或更好的方法,而不是strncpy将字符复制到目标位置。

您的问题 您正在使用malloc为指针分配内存,但随后将指针变量分配给具有自己地址的其他对象,而不是填充新分配的指针

解决方案 您应该使用strdup函数来分配内存并在分配的内存中复制字符串:

a_p = strdup("something");
a_p = malloc(N * sizeof(char));
strcpy(a_p, "something");
或者strcpy函数,该函数接受一个malloc'd指针和一个字符串以复制到指定内存中:

a_p = strdup("something");
a_p = malloc(N * sizeof(char));
strcpy(a_p, "something");
你的问题 您正在使用malloc为指针分配内存,但随后将指针变量分配给具有自己地址的其他对象,而不是填充新分配的指针

解决方案 您应该使用strdup函数来分配内存并在分配的内存中复制字符串:

a_p = strdup("something");
a_p = malloc(N * sizeof(char));
strcpy(a_p, "something");
或者strcpy函数,该函数接受一个malloc'd指针和一个字符串以复制到指定内存中:

a_p = strdup("something");
a_p = malloc(N * sizeof(char));
strcpy(a_p, "something");

我不是在改变指针指向的地方,你是在改变指针的值。。。是的,你正在改变指针的位置,我已经好几年没有写过C代码了,但我认为这就是字符串的工作方式。你得到了一个指向字符串,某物,内存中的地址的指针,它和你的malloc'ed内存的地址不同,这和我在这里遇到的问题是一样的。不是吗?你应该在代码中添加一些错误处理!示例:检查malloc是否返回NULL,这意味着malloc无法分配内存,您可能希望中止。@Ronan,您是对的,编写此命令只是为了复制错误并向用户解释它
我不是在改变指针指向的地方,你是在改变指针值。。。是的,你正在改变指针的位置,我已经好几年没有写过C代码了,但我认为这就是字符串的工作方式。你得到了一个指向字符串,某物,内存中的地址的指针,它和你的malloc'ed内存的地址不同,这和我在这里遇到的问题是一样的。不是吗?你应该在代码中添加一些错误处理!示例:检查malloc是否返回NULL,这意味着malloc无法分配内存,您可能希望中止。@Ronan,您是对的,写这篇文章只是为了复制错误并向社区解释它,避免冗长