简短回答
您不能定义大小未知的字符串。但当需要时,你可以使字符串变得越来越大。所有字符串和 I/O 函数都需要获取已分配的字符串才能使用,因此您必须稍微调整分配并注意不要超出分配的容量。
但是,当字符串长度有一个恒定的上限时,只需分配该长度的字符串就可以了。调整大小比较复杂,因此如果不需要,请避免这样做。
C中的字符串是什么
String 是 char 数组的一部分,以\0
。字符串函数在遇到第一个时停止读取数组\0
特点。请记住strlen返回字符数before首先\0
,所以即使数组在第一个之后立即结束\0
,字符串长度严格小于底层数组长度。具体来说,在这种情况下数组长度是strlen + 1
。这在分配字符串时很重要;总是为终止分配空间\0
!
E.g.
char w[7] = "Hello";
是相同的
char w[7] = {'H', 'e', 'l', 'l', 'o', '\0', '\0'};
当用作字符串时,第一个\0
是字符串的结尾,其后的任何内容都将被忽略(字符串函数不会读取)。即使您用可打印字符重写示例 char 数组的最后一个元素(例如w[6] = '!';
导致有{'H', 'e', 'l', 'l', 'o', '\0', '!'}
), puts(w);
将打印Hello
(not Hello!
或类似的东西)。
当使用字符串和字符数组时,请确保始终包含\0
在其末尾,否则在字符串函数读取数组后可能会出现未分配的内存,这会导致segfault.
为什么无法定义未知大小的字符串
正如我已经写过的,字符串是字符数组的一部分。每个数组必须有固定的大小。您可以仅使用其中的一部分(有效地使其更小),但必须对其进行分配和分配器(malloc, calloc)需要知道需要多少内存。
如果您使用的数组大于分配的数组,您的程序可能会崩溃segfault在更好的情况下。如果你非常不幸,你的程序不会崩溃,只会使用数组后面的部分内存,产生奇怪的结果。
从 C99 开始,如果可以的话,您可以省略数组长度规范从初始化器推断: char w[] = "Hello";
与以下结果相同char w[6] = "Hello";
。但是,这对您没有帮助,因为您在编译时指定了初始值设定项,并且需要在运行时动态更改字符串长度。
如何模拟任意长度的字符串
要处理无限长度的字符串,您可以创建固定长度的数组,每次其长度太低时,分配一个两倍长的新数组,并将原始内容复制到新数组中。 (和free旧的。)你可以使用realloc为您完成这项工作,当阵列不需要移动并且可以就地延长时,还有更高的速度的额外好处。