C函数使用指针更改字符串

我正在尝试创建一个从main函数更改char数组的函数,这就是我正在尝试做的事情:

#include  #include  #include  void change(char *a); int main() { char a[] = "hello"; printf("\na = %s", a); change(a); printf("%\na = %s", a); getch(); } void change(char *a) { a = "goodbye"; } 

这段代码存在一些问题,但首先我们需要退后一步,讨论如何在C中处理数组。

除非它是sizeof或一元&运算符的操作数,或者是用于初始化声明中的另一个数组的字符串文字,否则“N元素数组T ”的表达式将被转换(“衰减”)为表达式“指向T指针”,表达式的值将是数组的第一个元素的地址。

在宣言中

 char a[] = "hello"; 

"hello"是一个字符串文字,其类型为“6个元素的char数组”(5个字符加上0个终结符)。 由于它用于在声明中初始化数组a ,因此上述规则不适用; 相反,a的大小设置为与文字(6)的大小相同,并且字符串文字的内容被复制到数组。

当你从main调用change

 change(a); 

表达式 a具有类型“6元素char数组”。 由于它既不是字符串文字也不是sizeof或一元&运算符的操作数,因此该表达式将转换为“指向char指针”类型,并且表达式的值将是aray的第一个元素的地址。 因此,为什么将change函数声明为

 void change(char *a); 

在这种情况下, a只是一个指针。 当你写作

 a = "goodbye"; 

字符串文字"goodbye"没有在初始化程序中使用,它不是sizeof或一元&运算符的操作数,因此表达式转换为“指向char指针”类型,表达式的值是地址第一个角色。 那么这里发生的是你将字符串文字"goodbye"地址复制到a 。 这会覆盖a中的值,但是a与内存中的数组 a不是同一个内存中的对象,因此对它的任何更改都不会反映在main

如果要更新数组的内容 ,则需要使用库函数strcpy/strncpy (对于以0结尾的字符串)或memcpy (对于其他所有字符串),或者显式更新每个元素( a[0]='g'; a[1]='o'; a[2]='o';等)。

要更新a的内容,您可以使用

 strcpy( a, "goodbye" ); 

除了 ……

a只能容纳5个字符和0个终结符; "goodbye"是7个字符加0终结符; 它的两个字符大于能够存储的字符。 C将很乐意让你执行操作并在紧随其后删除字节,这可能会导致任何数量的问题(缓冲区溢出,例如这是一种典型的恶意软件攻击)。 在这个时刻你有两个选择:

首先,您可以声明a足够大以处理任一字符串:

 #define MAX_LEN 10 ... char a[MAX_LEN] = "hello"; 

其次,您可以将复制的字符串的大小限制a

 void change( char *a, size_t size ) { strncpy( a, "goodbye", size - 1 ); a[size - 1] = 0; } 

请注意,当您调用change时,您需要传递a可以存储的元素数作为单独的参数; 没有办法从指针告诉它指向的数组有多大:

 change( a, sizeof a / sizeof *a ); // although in this case, sizeof a would be // sufficient. 

主要问题是你通过这样做发送一个char pointeur a的副本:

 void change(char *a) { a = "goodbye"; } 

如果你想在其他函数中更改一个值,你应该这样做:

 #include  #include  #include  void change(char **a); int main() { char *a = "hello"; printf("\na = %s", a); change(&a); printf("%\na = %s", a); getch(); } void change(char **a) { *a = "goodbye"; } 

我改变了function,现在它可以这样工作:

 void change(char *a) { strcpy(a, "goodbye"); }