我不明白char数组和char *字符串之间的区别

时间:2015-10-04 00:04:10

标签: c

我做了以下小程序:

#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!";

我认为我的程序可以使用两种类型的'字符串'中的任何一种(正确的说法吗?),但它只适用于第一种。

为什么会这样?这两种类型有什么区别?

我需要对我的程序做些什么才能使用第二种类型的字符串?

2 个答案:

答案 0 :(得分:3)

声明

char greeting[] = "Hello!";

使编译器计算出字符串文字"Hello!"的大小(7个字符,包括终止'\0'),创建该大小的数组,然后将该字符串复制到该数组中。可以修改greeting的结果(例如,其字符被覆盖)。

声明

char * farewell="Goodbye!";

创建一个指针,指向字符串文字"Goodbye!"中的第一个字符。如果不调用未定义的行为,则无法修改该字符串文字。

可以将greetingfarewell传递给任何不尝试修改它们的函数。 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"的地址写入其中。由于这是一个指向字符串文字的指针,因此我们无法通过该指针写入文字的内容。