C中的字符串和指针

#include  #include  #include  int main(void) { char* a = malloc(5 * sizeof(char)); a = "1"; free(a); } 

关于上面的代码我有两个问题:

  1. 当我初始化这样的代码时,为什么代码会给free(a)带来错误:

a =“1”

并且在我初始化这样的时候不会给free(a)带来任何错误:

a [0] =’1’。

  1. 当我使用[0] =’1’初始化a并使用printf(“%s”,a)打印字符串a为什么我得到结果

‘1’ 没有用’\ 0’声明第二个索引?

mallocfree的规则是你必须只传递一个指针,该指针是通过调用malloc (或者它的一个等价物,如realloccalloc )分配的。 你不这样做:

 char* a = malloc(5 * sizeof(char)); a = "1"; free(a); 

当你自由呼叫时,你传递一个没有通过调用malloc分配的 这会导致您的程序具有未定义的行为。


你理解的问题是我怀疑你不明白a =“1”是做什么

我怀疑你想象这会将字符串复制到你分配给它的内存中。 它将指针a更改为指向不同的地址。

实际上,通过分配给a而不是它指向的内存,你正在泄漏分配的内存。 您的代码完全类似于:

 int i = 1; i = 2; 

我相信你可以看到i的初始化是没有意义的,因为你立即用新值覆盖i的值。 这正是你用指针做的。


您可以使用strcpy复制字符串。 像这样:

 char* a = malloc(5 * sizeof(char)); strcpy(a, "1"); free(a); 

同样,当你写作

 char* a = malloc(5 * sizeof(char)); a[0] = '1'; printf("%s", a); free(a); 

您正在分配调用malloc所分配的缓冲区的内容。 因此,对free的呼吁是正确的。

但是,当您这样做时,字符串不一定以空值终止。 您发现您的printf似乎有效,但这只是偶然的。

a [1]的内容是不明确的,似乎偶然地, [1]在运行程序时确实包含null。

这就是您通常使用strcpy之类的字符串函数来执行复制并确保空终止的原因。 你当然需要注意不要超出你的缓冲区。


最后,根据定义, sizeof(char)== 1所以你可以像这样编写malloc

 char* a = malloc(5); 

a = "1"; 正在为a分配只读内存。 a现在指向一个完全不同的内存位置。 之前返回的malloc现在已经丢失,因此您将无法释放内存。

这是一场灾难,因为不包括内存泄漏,在尝试free的新值时,您有未定义的行为繁荣 。 此外,如果您尝试修改那个未定义行为的内容。 繁荣

如果没有错误的重新分配, a[0] = '1'就完全可以了:您正在引用已分配字符缓冲区的第0个元素并将其值设置为文字1

但是,如果你在这个上尝试printf("%s", a) ,那么繁荣 ! 更多未定义的行为,因为您没有以空格终止printf要求您执行的字符缓冲区,以防止它访问您不拥有的内存。 为此,使用a[1] = 0

当你这样做

 a = "1"; 

a不再指向使用malloc分配的malloc 。 相反,它指向一个字符串常量,存储在程序的文本段中。 当然,这样的指针不能被释放。 原来a指针丢失了。

至于你的第二个问题,那就是未定义的行为。 a [1]恰好是一个空虚的角色,纯粹是愚蠢的运气,但你当然不应该依赖于这种情况。

 a = "1"; 

指向一个字符串文字,它存储在只读存储器中。 你不能free()那部分记忆。

a[0] = '1'; 使它在a指向的第一个字节中存储值31 (因为这是1的hexascii值)。 a仍然指向malloc已经返回的地址,因此释放它是合法的操作。 a[0]*(a + 0) ,因此您可以看到a地址未被触及,即更改点的内容。

其他答案已经有关于null终止char数组的信息。 您应该知道printf()在它吸引空终止符时停止向stdout写入值。 如果在第0个位置存在'1'在数组的第1个位置没有'\0' ,则可能会看到一些垃圾值。

你应该知道"1"'1'是两个不同的东西。

修正了带有内联注释的程序,以便您理解:

 int main(void) { char* a = (char *) malloc(5 * sizeof(char)); // prefer casting from void * to char * // a = "1"; -- wrong conversion from string constant to char * strcpy(a, "1"); // this would work free(a); }