第 11 章 字符串

字符串

一、字符串定义

​ 字符串是以空字符( \0 )结尾的 char 类型数组。

二、在程序里定义字符串

有多种方法可以定义字符串:字符串常量、char 类型数组、指向 char 的指针。

2.1 字符串常量

​ 用双引号括起来的内容称为字符串字面量,也叫做字符串常量。双引号中的字符和编译器自动加入末尾的 \0 字符,都作为字符串储存在内存中。

​ 字符串常量属于静态存储类别,这说明如果在函数中使用字符串常量,该字符串只会被储存一次,在整个程序的生命期内存在。

​ 用双引号括起来的内容被视为指向该字符串存储位置的指针。

2.2 字符串数组和初始化

​ 定义字符串的时候,必须让编译器知道需要多少空间。

​ 两种方法:

​ Ⅰ. 使用足够空间的数组存储字符串。 如 char a[50] = “alkdjfaldkfjaldkf”;

​ Ⅱ. 让编译器来确定数组的大小。 如:char a[] = “aldkjfaldkfalkdfj”;

​ 第二种方法方便,但是该方法初始化的字符串不能再追加新的内容。

2.3 数组和指针

​ 数组声明字符串:char arr[] = “arry and pointer.”;

​ 指针声明字符串:const char * pt = “arry and pointer.”;

​ 以上两种声明,pt 和 arr 都是该字符串的地址。在这两种情况下,带引号的字符串本身决定了预留给字符串的存储空间。但是这两种方式还是有不同。

​ **字符串常量存储在静态存储区中,**但是,程序在运行的时候才会为数组分配内存,所以在运行时才把字符串拷贝到数组中。这时该字符串有两个副本,一个是静态内存中的字符串字面量,另一个是存在 arr 数组中的字符串。

​ 而指针是存储了字符串在静态存储区的位置,因此这种方式的字符串只有一个副本。

注意:arr 是地址常量,而 pt 是指针变量,因此不能进行 arr++ 这种操作,但 pt++ 却可以取出下一个位置的元素。

例1:

#include <stdio.h>

#define MSG "I'm a const string!"
int main(void)
{
        char arr[] = MSG;
        char * pt = MSG;

        printf("address of MSG is : %p \n", MSG);
    	//指定字符串与 MSG 内容相同
        printf("address of \"I'm a const string!\" is : %p \n", "I'm a const string!");
        printf("address of pt is : %p \n", pt);
        printf("address of arr is : %p \n", arr);

        return 0;
}
/*输出结果:
address of MSG is : 0x400650 
address of "I'm a const string!" is : 0x400650 
address of pt is : 0x400650 
address of arr is : 0x7ffce33adba0 
*/

​ 分析结果:

​ 两个字符串常量的地址一样,说明相同的字符串常量只存储了一次(与编译器采取的策略有关);指针与 MSG 的地址一样,说明指针是直接使用的原字符串,arr 与 MSG 的地址不一样,说明 arr 使用的是字符串的拷贝。

​ 字符串常量被视为一个 const 类型的数据,因此应该使用指向 const 的指针。即:const char * pt = MSG;

例2:

#include <stdio.h>

#define MSG "I'm a const string!"
int main(void)
{
        char arr[] = MSG;
        char * pt = MSG;

        printf("pt[0] is: %s\n", pt);
        printf("pt[1] is: %s\n", ++pt);
        printf("arr[0] is: %s\n", arr);
    	/*输出结果:
    	pt[0] is: I'm a const string!
		pt[1] is: 'm a const string!
		arr[0] is: I'm a const string!
		*/
    
        printf("arr[1] is: %s\n", ++arr);
    	/*编译错误:
    	arr_pt2.c: In function ‘main’:
		arr_pt2.c:12:27: error: lvalue required as increment operand
  			printf("arr[1] is %s\n", ++arr);
  		*/

        return 0;
}

分析结果:

​ 该结果说明 pt 是变量,而数组名 arr 是地址常量,但是数组的元素是变量。

2.4 指针数组

#include <stdio.h>

int main(void)
{
	int i;
    //声明指针数组
	const char *ptarry[5] = { "aaaaaaaaaaaa", "bbbbbbbbbbbbb", "ccccccccccccccc", "dddddddddddd", "eeeeeeeeeeee" };
    //声明普通数组
	char arry[5][40] = { "aaaaaaaaaaaa", "bbbbbbbbbbbbb", "ccccccccccccccc", "dddddddddddd", "eeeeeeeeeeee" };

	printf("%-36s %-25s\n", "ptarry", "arry");

	for (i = 0; i < 5; i++)
		printf("%-36s %-25s\n", ptarry[i], arry[i]);

	printf("\n size of ptarry is : %zd, size of arry is %zd", sizeof(ptarry), sizeof(arry));

	return 0;
}
/*运行结果
ptarry                               arry                     
aaaaaaaaaaaa                         aaaaaaaaaaaa             
bbbbbbbbbbbbb                        bbbbbbbbbbbbb            
ccccccccccccccc                      ccccccccccccccc          
dddddddddddd                         dddddddddddd             
eeeeeeeeeeee                         eeeeeeeeeeee             

 size of ptarry is : 40, size of arry is 200
*/

运行结果:

​ ptarry 的大小是 40字节, 而 arry 的大小是 200字节(具体大小与系统有关),因为在本系统中一个指针占 8 字节,即 64 位,所以 5 个指针占了 40 字节,而 arry 是 5 * 40 = 200 字节。

参考书籍

C Primer Plus (第六版)中文版

发布了42 篇原创文章 · 获赞 3 · 访问量 2089

猜你喜欢

转载自blog.csdn.net/stable_zl/article/details/104094605
今日推荐