C++中多字符串拼接式字符数组初始化的原理及与列表初始化的对比
关于C++字符数组两种初始化方式的解析
嘿,刚接触C++遇到这种写法很正常,我来给你捋清楚这两种初始化方式的区别和工作原理!
一、const char charset[] = "abc..." "ABC..." "012...";的工作原理
这其实是C++(以及C)里一个很实用的语法特性:相邻的字符串字面量会在编译阶段被自动拼接成一个完整的字符串。
也就是说,你写的这三个用双引号包裹的字符串,编译器会把它们合并成一个长字符串:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYS0123456789",然后用这个完整的字符串来初始化字符数组charset。
另外要注意,用字符串字面量初始化字符数组时,编译器会自动在数组末尾添加一个'\0'(空字符,C风格字符串的终止符),所以charset的实际长度是所有可见字符的数量加1,这个'\0'是编译器帮你偷偷加上的,不用手动写。
这种写法特别适合把很长的字符串拆成多行来写,既保持代码可读性,又不会影响最终的字符串内容——完全等价于把所有字符写在一个双引号里。
二、和char tmp[] = {'a','b','c',...};列表初始化的区别
这两种方式核心差异很大,主要体现在这几个方面:
- 是否自动添加终止符:
用列表初始化时,编译器只会把你列出的字符挨个放进数组里,不会自动添加'\0'。比如char tmp[] = {'a','b','c'};,这个数组的长度是3,里面只有'a'、'b'、'c'三个字符,没有终止符。如果你用strlen(tmp)这类C字符串函数去操作它,会因为找不到终止符而越界访问,导致未定义行为。
而字符串字面量初始化的数组,末尾必然有'\0',可以安全地作为C风格字符串使用。 - 写法便捷性:
对于长序列的字符,字符串拼接的写法明显更简洁——你不用给每个字符加单引号和逗号,直接拆分字符串就行。列表初始化适合字符数量少、需要精确控制每个元素的场景。 - const属性的意义:
你的例子里用了const char,这是因为字符串字面量本身是不可修改的(C++标准里字符串字面量的类型是const char[]),用const修饰数组可以避免不小心修改它导致的未定义行为。而列表初始化的数组如果不加const,是可以修改其中字符的(比如tmp[0] = 'x';是合法的)。 - 编译阶段的处理:
字符串拼接是在编译时完成的,编译器直接生成合并后的字符串常量,没有运行时开销;列表初始化则是编译时逐个把字符赋值到数组中,虽然开销也很小,但逻辑上是不同的。
举个直观的例子
你的charset数组,完全等价于:
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYS0123456789";
而如果用列表初始化写等价的可作为C风格字符串的数组,你得手动加'\0':
const char charset[] = {'a','b','c',...,'9','\0'}; // 要把所有字符列出来,最后还要加'\0'
这显然麻烦很多!
内容的提问来源于stack exchange,提问作者Ethan Leong
相关产品推荐
相关产品推荐

