1. 字符串常量不可修改
让我们回顾一下字符串常量的知识。
#include <stdio.h>
int main()
{
printf("sizeof HelloWorld = %d\n", sizeof("HelloWorld"));
return 0;
}
字符串常量"HelloWorld"
占用11个字节。
字符串常量在内存中,由每个字符的ASCII码按照顺序排列构成,每个字符仅占一个字节,并且末尾会附上一个数值0,指示字符串结尾。
字符'0'对应的ASCII码为十进制48。而标记字符串结尾的数值0,为了不与字符'0'冲突,使用转义序列'\0'表示。
字符'0'的ASCII编码为48。
而转义字符'\0'的ASCII编码为0。
字符串常量是无法被修改的,现在我们来探究一下这个问题。
#include <stdio.h>
int main()
{
char *pStr = "HelloWorld\n";
printf("%s", pStr);
pStr[0] = 'h';
printf("%s", pStr);
return 0;
}
我们知道字符串常量实际上是一个字符数组,因此"HelloWorld\n"
的类型为char [12]
的字符数组。而数组出现在表达式中,将转换为指向首元素的指针char *
。即pStr
指向字符串常量的第一个元素'H'
。
之后,我们尝试将第一个字符从'H'修改为'h'。运行后程序报错了。
结论:字符串常量是常量,而常量不能被修改。
2. 正确初始化字符数组
若需要修改字符串,则需要使用字符数组来装载字符串,并修改字符数组中的字符。而不能直接修改字符串常量。
现在,初始化一些字符数组。并复习一下,哪些字符串能够被正常结尾。
// 初始化列表长度小于字符数组长度
char str1[10] = {'H', 'e', 'l','l','o'};
char str2[10] = {'H', 'e', 'l','l','o','\0'};
// 初始化列表等于字符数组长度
char str3[6] = {'H', 'e', 'l','l','o', '\0'};
char str4[5] = {'H', 'e', 'l','l','o'};
// 使用字符串初始化字符数组
char str5[10] = "Hello";
char str6[6] = "Hello";
char str7[5] = "Hello";
// 省略字符数组大小
char str8[] = {'H', 'e', 'l','l','o','\0'};
char str9[] = {'H', 'e', 'l','l','o'};
char str10[] = "Hello";
str1:字符数组共有10个元素。前5个元素被初始化为'H'、'e'、'l'、'l'、'o',其后所有的元素填0。元素'o'后填0,而'\0'的数值就为0。 字符数组中的字符串得以正常结尾。
str2:字符数组共有10个元素。前6个元素被初始化为'H'、'e'、'l'、'l'、'o'、'\0',其后所有的元素填0。初始化时,本身就在字符串结尾添加了'\0'。 字符数组中的字符串得以正常结尾。
str3:字符数组共有6个元素。并且被初始化为'H'、'e'、'l'、'l'、'o'、'\0'。 字符数组中的字符串得以正常结尾。
str4:字符数组共有5个元素。并且被初始化为'H'、'e'、'l'、'l'、'o'。没有'\0'作为结尾标记。 字符数组中的字符串得以无法结尾。
str5:字符数组共有10个元素。前6个元素被初始化为'H'、'e'、'l'、'l'、'o'、'\0',其后所有的元素填0。 字符数组中的字符串得以正常结尾。
str6:字符数组共有6个元素。并且被初始化为'H'、'e'、'l'、'l'、'o'、'\0'。 字符数组中的字符串得以正常结尾。
str7:字符数组共有5个元素。并且被初始化为'H'、'e'、'l'、'l'、'o'。没有'\0'作为结尾标记。 字符数组中的字符串得以无法结尾。
str8:字符数组长度由初始化列表决定。初始化列表中有6个元素,那么字符数组长度为6。并且被初始化为'H'、'e'、'l'、'l'、'o'、'\0'。 字符数组中的字符串得以正常结尾。
str9:字符数组长度由初始化列表决定。初始化列表中有5个元素,那么字符数组长度为5。并且被初始化为'H'、'e'、'l'、'l'、'o'。没有'\0'作为结尾标记。 字符数组中的字符串得以无法结尾。
str10:字符数组长度由字符串常量决定。字符串常量中有6个元素,那么字符数组长度为6。使用字符串常量初始化字符数组。 字符数组中的字符串得以正常结尾。