- char str[5] = {
- 'h', 'e', 'l', 'l', 'o'
- };
- printf("%s", str);
执行后会发现打印出来前面是对的, 但是后面会携带一些乱码 (这些乱码在各个平台的表现形式不同), 原因是 printf 中 %s 输出方式是检测直到遇到'\0'为止, 它并不管你这个字符串(在这里就是 str 这个字符数组) 是多长的, 只认为我遇到了'\0'就认为这个字符串结束, 所以连带打出了后面一些无法预知的符号, 也就是乱码, 直到遇到'\0', 也就是我们俗称的结束符.
那既然字符串是以结束符作为结尾的, 那就可以手动给这个 str 字符串添加一个'\0':
char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
注意'\0'也是占据一个字节的, 所以此时 str 的长度变成了 6, 当然也可以省略不写数组长度, 但实际有效字符其实是 5 个.
刚提到这种写法很难一眼看出这是一个字符串, 至少在我们的认知中, 更容易接受像 "hello" 这种直观的表示方法, 因此 C 提供了一种直观的初始化字符数组的方法:
char str[6] = {"hello"};
这种写法, 不需要显示的写出结束符, 但是要给结束符预留一个字符, 也就是一个字节的位置, 所以一样的, str 长度为 6, 有效字符还是 5 个.
通常我们把 {} 省略, 用字符数组表示字符串的最简便形态就是:
char str[6] = "hello";
char * 字符串
按照正常的理解 char * 理应像 int * 之类的基本类型一样, 表示指向的位置存放着一个 char 类型的变量, 也就是指向的是一块 1 个字节的内存地址, 也就是这样:
- char a = 'A';
- char * p = &a;
- printf("%c", *p); // A
但是为什么能够用 char * 表示一个字符串?
因为在 C 语言中像 "hello" 这样的字符串本质是用一个地址来表示, 用的就是 "hello" 中的首地址也就是'h'字符的地址.
这样的话就可以用 char * 来表示一个字符串, 更准确的说是指向这个字符串的首地址:
char* str = "hello";
区别
首先从本质上就是有区别的, char[]是遵循的是数组的规则, 含有数组的特性; char * 遵循的是指针的规则, 含有指针的特性.
其次当使用 char* str = "hello" 时, 编译器会在常量区创建一个字符串常量 "hello", 然后 str 指向这个字符串常量, 编译器在编译时就知道 str 指向的是一个常量.
而 char[]虽然是写成 char str[] = "hello", 但是是在运行时将 "hello" 中的字符逐个放入 str 数组中, 所以此时的 "hello" 并不是常量, 而是被拆成了栈上 str 数组中的各个元素.
因此, 使用 char* str = "hello" 后, 不能够通过 str 指针来改变常量 "hello"; 使用 char[] str = "hello" 后, 依然能够改变数组中的各个字符.
那么可能我们会好奇, 既然 char* str = "hello" 中的 "hello" 是常量, 为什么还允许我们通过 char* str 获取指向 "hello", 万一我们通过 str 企图改变 "hello" 不是很危险吗?
其实编译器会警告我们:
warning: ISO C++ forbids converting a string constant to 'char*'
禁止将不变字符串转为 char*, 如何避免这种警告呢? 既然编译器不想我们改, 我们就主动告诉它我没有想要改变常量字符串的企图即可:
const char* str = "hello";
来源: http://www.bubuko.com/infodetail-3651864.html