You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中字符数组为何能容纳超出初始化大小的字符?

问题:C语言中字符数组越界拼接为何能正常输出?

我想在C语言中拼接两个字符数组,找到了如下代码。我知道数组初始化后无法调整大小,实现动态字符数组可使用动态内存分配(Dynamic Memory Allocation)。但代码中,char数组first初始化大小为8字节(含"\0"),将其传入concatenateStrings函数后,形参dest数组大小应为8字节,而大小为7字节的src数组被拼接到dest中,最终dest包含13个字符。执行程序时,sizeof(dest)为8,strlen(dest)为13,请问为何dest数组能容纳超出其初始化大小的字符?

附代码:

#include <stdio.h>
#include <stdlib.h>
void concatenateStrings(char dest[], const char src[]) {
/* Find the end of the destination string (null terminator) */
int i = 0;
while (dest[i] != '\0') {
    i++;
}

/* Copy characters from src to the end of dest */
int j = 0;
while (src[j] != '\0') {
    dest[i++] = src[j++];
}

/* Add null terminator to the concatenated string */
dest[i] = '\0';
printf("dest string: %d\n", sizeof(dest));
printf("dest len string: %d\n", strlen(dest));
printf("src string: %d\n", sizeof(src));
}

int main() {
char first[] = "Hello, ";
char second[] = "World!";

printf("First string: %d\n", sizeof(first));
printf("Second string: %d\n", sizeof(second));

concatenateStrings(first, second);

printf("Concatenated string: %s\n", first);

return 0;
}

解答

这个现象本质是数组越界访问的未定义行为,并非数组真的“容纳”了更多字符,以下是关键原因拆解:

  • 函数参数中数组会退化为指针
    当你把数组first传入concatenateStrings函数时,形参char dest[]本质上等价于char *dest——它只是一个指向数组首元素的指针,而非真正的数组。此时sizeof(dest)计算的是指针的大小(64位系统下为8字节,所以输出8),完全和原数组的实际大小无关。

  • strlen只认\0终止符
    strlen的工作逻辑是从起始地址开始计数,直到遇到第一个\0为止,它不会检查内存是否属于当前数组的合法空间。你的代码里把src的字符写到了first数组的边界之外,最后又添了一个\0,strlen就会从first的首地址一直数到这个新的\0,得到13的结果,但这部分超出的内存根本不是first数组的合法区域。

  • 越界访问只是“碰巧”没触发错误
    C语言不会自动检查数组的边界,当你往first数组外面写数据时,实际上是在修改数组相邻的内存区域。如果这块内存刚好没有被其他变量或程序关键数据占用,程序可能暂时不会崩溃,还能正常输出结果,但这完全是运气——一旦这块内存被其他数据占用,就会导致程序崩溃、数据错乱等不可预测的问题,这就是C语言中的未定义行为。

  • 正确的做法是用动态内存分配
    要安全拼接字符串,应该先计算两个字符串的总长度,然后用malloc或calloc申请足够的内存,拼接完成后记得用free释放内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Jed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 22:07:33