为什么修改字符串的代码不起作用?

对于c风格的字符串,如何将字符指针指向的内存地址赋予char? 例如,在下面的示例中,我想将num更改为“123456”,因此我尝试将p设置为“0”所在的数字,并尝试用“4”覆盖它。 谢谢。

#include  #include  int main() { char* num = (char*)malloc(100); char* p = num; num = "123056"; p = p+3; //set pointer to where '4' should be p = '4'; printf("%s\n", num ); return 0; } 

该代码不起作用,仅仅因为该行:

 num = "123056"; 

更改num以指向远离分配的内存(并且p仍然指向该内存,因此它们不再是相同的位置)到最可能的只读内存。 您不能更改属于字符串文字的内存,它是未定义的行为。

您需要以下内容:

 #include  #include  int main (void) { char *num = malloc (100); // do not cast malloc return value. char *p = num; strcpy (num, "123056"); // populate existing block with string. p = p + 3; // set pointer to where '0' is. *p = '4'; // and change it to '4'. printf ("%s\n", num ); // output it. return 0; } 

首先,当你这样做时:

 num = "123056"; 

您没有将字符串“123056”复制到malloc()分配的堆区域。 在C中,指定一个char *指针,字符串文字值相当于将其设置为常量 – 即与以下内容相同:

 char str[] = "123056"; 

那么,你刚刚完成的是你已经放弃了对malloc()分配的100字节堆区域的唯一引用,这就是你的后续代码没有打印正确值的原因; ‘ p ‘仍然指向malloc()分配的堆区域(因为num在赋值时指向它),但num不再。

我假设您实际上打算将字符串“123056” 复制到该堆区域。 以下是如何做到这一点:

 strcpy(num, "123056"); 

虽然,出于各种原因,这是更好的做法:

 strncpy(num, "123056", 100 - 1); /* leave room for \0 (null) terminator */ 

如果你刚刚完成:

 #include  #include  #include  int main(void) { char *num = malloc(100); char *p = num; strncpy(num, "123056", 100 - 1); p = p + 3; *p = '4'; printf("%s\n", num); return 0; } 

你会得到正确的结果:

 123456 

您可以签订此操作合同:

 p = p + 3; *p = '4'; 

…并避免迭代指针,方法如下:

 *(p + 3) = '4'; 

其他几点说明:

  • 虽然常见的风格实践,但不需要将malloc()的返回值转换为(char *) 。 C语言保证void *类型的转换和对齐。

  • 总是检查malloc()的返回值。 如果堆分配失败(即你的内存不足),它将为NULL,此时你的程序应退出。

  • 根据实现, malloc()分配的malloc()区域在某些情况下可能包含陈旧的垃圾。 分配后将其归零是一个好主意:

     memset(num, 0, 100); 
  • 永远不要忘记free()你的堆! 在这种情况下,程序将退出,操作系统将清理你的垃圾,但如果你没有养成这种习惯,你很快就会有内存泄漏。

所以,这是“最佳实践”版本:

 #include  #include  #include  int main(void) { char *num, *p; /* * Don't take 1-byte chars for granted - good habit to get into. */ num = malloc(sizeof(char) * 100); if(num == NULL) exit(1); memset(num, 0, sizeof(char) * 100); p = num; strncpy(num, "123056", 100 - 1); *(p + 3) = '4'; printf("%s\n", num); free(num); return 0; } 

除了其他人指出的* p问题之外,您还有内存使用问题。 你有一个100字节的缓冲区,内容未知。 你有另一个7字节的缓冲区,包含字符串“123056”和一个空终止符。 你这样做:

  1. num设置为指向100字节缓冲区
  2. p设置为指向num; 即,它指向100字节缓冲区
  3. 你重置num指向7字节缓冲区; p仍指向100字节缓冲区
  4. 使用p修改100字节缓冲区
  5. 然后使用num打印出7字节缓冲区

因此,您不打印正在修改的缓冲区。

嗯,你知道p是指针类型。 它存储char’0’的地址。 如果为p赋值’4’。 它将以’4’作为地址。 但是,地址’4’是非法的。 您可以使用’*’运算符来获取存储在p中的地址的值。

只需使用*p = '4'; …!