我做了以下小程序:
#include <stdio.h>
void strncpy(char * s, char * t, int n);
int
main()
{
char string1[]="Learning strings";
char string2[10];
strncpy(string2,string1,3);
printf("string1:%s\nstring2:%s\n",string1,string2);
return 0;
}
void strncpy(char * s, char * t, int n)
{
int i;
for(i=0; i<n && t[i]!=0;i++)
s[i]=t[i];
s[i]=0;
}
我试图了解做以下事情之间的区别:
char greeting[]="Hello!";
并且
char * farewell="Goodbye!";
我认为我的程序可以使用两种类型的'字符串'中的任何一种(正确的说法吗?),但它只适用于第一种。
为什么会这样?这两种类型有什么区别?
我需要对我的程序做些什么才能使用第二种类型的字符串?
答案 0 :(得分:3)
声明
char greeting[] = "Hello!";
使编译器计算出字符串文字"Hello!"
的大小(7个字符,包括终止'\0'
),创建该大小的数组,然后将该字符串复制到该数组中。可以修改greeting
的结果(例如,其字符被覆盖)。
声明
char * farewell="Goodbye!";
创建一个指针,指向字符串文字"Goodbye!"
中的第一个字符。如果不调用未定义的行为,则无法修改该字符串文字。
可以将greeting
或farewell
传递给任何不尝试修改它们的函数。 greeting
也可以传递给任何修改它的函数(只要修改字符greeting[0]
到greeting[6]
,而不修改其他字符)。如果修改了farewell
,则结果是未定义的行为。
一般来说,最好将farewell
的定义更改为
const char * farewell="Goodbye!";
实际上反映了它的真实性质(例如,如果将farewell
传递给期望非const
参数的函数,则会导致编译错误。可以将farewell
定义为非const
指针,同时指向字符串文字的(第一个字符)是历史异常。
当然,如果您希望farewell
可以安全地修改,请将其声明为数组,而不是指针。
答案 1 :(得分:1)
字符串文字"Hello"
和"Goodbye"
存储为char
的数组,以便它们在程序启动时分配并在程序退出时释放,并在整个程序中可见。它们可以以不能修改的方式存储(例如在只读数据段中)。尝试修改字符串文字的内容会导致未定义的行为,这意味着编译器不需要以任何特定方式处理该情况 - 它可能以您希望的方式工作,它可能导致分段违规,或者它可能会这样做。
该行
char greeting[] = "Hello";
分配足够的空间来保存文字的副本,并将文字的内容写入其中。您可以随意修改此数组的内容(尽管您不能将超过"Hello"
的字符串存储到其中)。
该行
char *farewell = "Goodbye";
创建一个指针并将字符串文字"Goodbye"
的地址写入其中。由于这是一个指向字符串文字的指针,因此我们无法通过该指针写入文字的内容。