一. 简介
本文学习了 C语言中数组与指针的区别。这样的话,可以在编写C代码时规避掉出错的问题。
二. C语言中数组与指针的区别
1. 数组
定义字符串数组时,必须让编译器知道需要多少空间。
一种方法是用足够空间的数组存储字符串。例如如下:
char buf[40] = "hello world!";
或者 如下:
char buf[40] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0'};
注意,最后的空字符。没有 '\0'就不是一个字符串,而是一个字符数组。
通常,让编译器确定数组的大小很方便。回忆一下,省略数组初始化声明中的大小,编译器会自动计算数组的大小,如下所示:
char buf[] = "hello world!";
让编译器计算数组的大小只能用在初始化数组时,如果创建一个稍后再填充的数组,就必须在声明时指定大小。
2. 指针
可以用指针表示法创建字符串。例如如下:
char *ptr = "hello world!";
3. 以上数组与指针有什么区别?
数组
数组形式在计算机的内存中分配为一个内含 13(还包括 '\0')个元素的数组,每个元素被初始化为字符串常量对应的字符。
通常字符串都作为可执行文件的一部分存储在数据段中,当把程序载入内存时,也载入了程序中的字符串。字符串存储在静态存储区中,但是,程序在开始运行过时才会为该数组分配内存。此时,才将字符串拷贝到数组中,注意,此时字符串有两个副本,一个是静态内存中的字符串常量,另一个是存储在 buf数组中的字符串。
这里关键要理解,在数组形式中,数组 buf是地址常量。不能更改 buf,如果改变了 buf,则意味着改变了数组的存储位置(即地址)。
可以进行类似 buf+1 这样的操作,标识数组的下一个元素。但是,不允许进行 ++buf这样的操作,递增运算符只能用于变量名前,不能用于常量。
指针
指针形式 (*ptr) 也使得编译器为字符串在静态存储区预留了 13个元素的空间,另外,一旦开始执行程序,它会为 指针变量 ptr 留下一个存储位置,并把字符串的地址村存在指针变量中,该变量最初指向该字符串的首地址。
但是它的值可以改变。因此,可以使用递增运算符,例如:
++ptr //指向第2个字符
总之,初始化字符数组把静态存储区的字符串拷贝到数组中,而初始化指针只把字符串的地址拷贝给指针。
数组与指针使用上的区别
初始化字符数组来存储字符串和初始化指针来指向字符串有何区别?
(指向字符串:指向字符串的首字符)
例如,有如下声明:
char buf[] = "come on, TangSan!";
char* ptr = "come on, Xiao Wu!";
两者的主要区别是:数组名 buf是常量,而指针名 ptr是变量。那么实际使用有什么区别?
首先,两者都可以使用数组表示法:
for(i=0; i< 10; i++)
printf("%c", buf[i]);
for(i=0; i< 10; i++)
printf("%c", ptr[i]);
其次,两者都能进行指针加法操作:
for(i=0; i< 10; i++)
printf("%c", *(buf+i));
for(i=0; i< 10; i++)
printf("%c", *(ptr+i));
但是,只有指针标识法可以进行递增操作:
for(i=0; i< 10; i++)
printf("%c", *(ptr++));
而对于指针 ptr,是否可以进行如下操作:
ptr[1] = '1';
《C primer Plus》书籍说,编译可能允许这样做,但是对当前的 C标准而言,这样的行为还未定义的。例如,这样的语句可能导致内存访问错误。原因是编译可以使用内存中的一个副本来表示所有完全相同的字符串常量。
但是,我这边在 ubuntu系统上经过测试是不行的,会报段错误。