字符串几种定义方式的对比
- 一. 字符串的定义方式
- 1. 利用字符指针创建字符串
- (1.1)利用字符指针创建字符串,只能用字符串常量的方式进行初始化
- 2. 利用字符数组创建字符串
- (2.1)情况1:定义了字符数组的长度
- (2.2)情况2:省略了定义数组长度
- 3. 利用字符串常量来初始化字符数组
- 二. 字符指针创建字符串和字符数组创建字符串的区别
- 补充
一. 字符串的定义方式
C语言中的字符串是被当作字符数组来处理的,也就是说字符串是一种特殊的字符数组。字符串中的字符是逐个存放到字符数组中的。C语言中规定了‘\0’为字符串结束标志,设某字符数组中存在若干个有效字符,第n个字符为’\0’,那么前n-1个字符就组成了一个字符串,到‘\0’时字符串结束。
1. 利用字符指针创建字符串
(1.1)利用字符指针创建字符串,只能用字符串常量的方式进行初始化
const char *d = “123456”;
printf(“d[0]:%c\n”, d[0]); // 输出:1
printf(“d:%s\n”, d); // 输出:123456
2. 利用字符数组创建字符串
(2.1)情况1:定义了字符数组的长度
char arr[5] = { ‘1’,‘2’,‘3’,‘4’,‘5’ };
printf(“%s”, arr); //: 输出12345烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
printf(“arr[0]:%c\n”, arr[0]);//输出:1 输出字符正常
注意:
(1)这里输出字符串会乱码,因为字符串以\0作为结尾标志的,编译器直到找到\0才会停止。
(2)字符数组不会要求他的最后一个字符为\0,甚至可以不包含\0,所以上面定义的字符数组合法,如果定义的是字符串则必须要以\0作为结尾的标值。
因此有两种方式可以修改上面的语句:
第一种:
char arr2[6] = { ‘1’,‘2’,‘3’,‘4’,‘5’ };
第二种:
char arr2[6] = { ‘1’,‘2’,‘3’,‘4’,‘5’,‘\0’};
printf(“arr2:%s\n”, arr2);//输出123456
注意:
(1)上面两种修改方式等价。
(2)如果字符数组的长度大于我们设定的元素个数,其余的空元素会自动转化为\0。
(2.2)情况2:省略了定义数组长度
char arr3[] = { ‘1’,‘2’,‘3’,‘4’,‘5’ };// 输出12345烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫…
注意:
(1)数组长度会自动定为5,因此输出乱码原因同情况1一样
(2)\0会占一个字节空间,但不会输出,因此想要上式输出字符串,必须加\0字符结尾
因此可以修改为:
char arr3[] = { ‘1’,‘2’,‘3’,‘4’,‘5’,‘\0’};// 输出12345
3. 利用字符串常量来初始化字符数组
char arr4[] = { “123456” };
char arr4[] = “123456”;
printf(“arr4[]:%s\n”, arr4);// 输出123456
注意:
(1)上面两式等价
(2)以“”这种字符串常量的方式进行存储时,系统会自动在最后一个字符的后面加上一个’\0’,作为字符串结束标志。
(3)char a[] = “123456” 和 char a[] = { ‘1’,‘2’,‘3’,‘4’,‘5’,‘\0’}是等价的。与 char a[] = { ‘1’,‘2’,‘3’,‘4’,‘5’}不是等价的
二. 字符指针创建字符串和字符数组创建字符串的区别
const char *a = "123456";
char a[] = "123456";
区别:
● 这两行代码从实现上来看,它两的实现功能是一样的,都是初始化一个字符串。
● 两者都可以通过访问数组元素,且都代表数组中首元素的地址,都可以通过下标查找/输出某字符。
如下所示:
const char *d = "123456";
printf("%d\n", (int*)d); 地址输出:709729692
printf("%d\n", (int*)&d[0]); 地址输出:709729692
printf("%d\n", (int*)&d[1]); 地址输出:709729693
printf("%c\n", d[0]); 输出:1
printf("%c\n", *d); 输出:1
char a[] = "123456";
printf("%d\n", (int*)a); 地址输出:1320154980
printf("%d\n", (int*)&a[0]); 地址输出:1320154980
printf("%d\n", (int*)&a[1]); 地址输出:1320154981
printf("%c\n", a[0]); 输出:1
printf("%c\n", *a); 输出:1
● 从计算机系统中的段式内存存储方式来看,两种初始化字符串的方式是有区别的:
对于: ;
是指向其字符串常量的地址的,但是字符串常量的地址通常存放在代码段(.text)区域,这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,不能对其数据进行修改。因此我们需要在其数据类型名前加上进行修饰,也就是一个常量指针,确保使a指向的字符串内容不可以被修改。
如下:
const char *a = "123456";
a[1] = '6';//报错输出:表达式必须是可修改的左值
对于: ;
是一个初始化的变量。如果是局部变量,则指向栈上的内存区域。如果是 static 或全局变量则指向进程的 数据段(.data)内存区域。data 段权限是可读、可写;也就是可以修改其值。
如下
char a[] = "123456";
a[1] = '6';
printf("%s",a);//正常输出:163456
补充
利用字符串常量的初始化方式去定义字符数组,即 ;
对字符数组的操作和普通数组的操作是一样的,比如上式种的
char a[] = "123456";
*a = '6';
printf("%s", a);//输出623456