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"); }