C语言代码运行缺失1项预期输出的问题排查与修复
代码问题根因
代码存在两个会触发未定义行为的严重bug,直接导致运行时输出缺失:
- 数组越界访问
循环中使用7*i作为指针c的偏移量计算访问位置,但数组a的总长度只有11字节(初始化字符串"0123456789"会自动在末尾补'\0'占1字节),合法下标范围是0~10。当i=2时偏移量已经到14,i=4时偏移量到28,远远超出a的内存边界,会读取栈上的随机脏数据,甚至可能访问到不可读的内存页触发程序异常终止。 - 字符数组b未添加字符串终止符
数组b长度为5,循环刚好写满5个字符位置,没有预留空间存放C语言字符串要求的结束标志'\0'。当执行printf("%s\n", b)时,%s格式符会从b的首地址开始持续向后读取内存,直到碰到任意值为0的字节才会停止输出:这一过程要么打印大量乱码,要么读到受保护的内存地址触发段错误,直接让程序提前退出,后面的第4项打印逻辑根本不会执行,就是你看到的缺输出现象。
修复方法
按以下两点修改即可:
- 修正循环中的偏移计算逻辑,不要超出数组a的合法访问范围。从代码上下文看,
7*i大概率是笔误,如果是要顺序读取a中的字符,直接用偏移i即可;如果是要从a的指定位置开始读取,用起始位置+i即可,注意计算后的偏移不要超过a的下标上限。 - 给b数组补字符串终止符:要么把b的长度多留1字节存
'\0',要么在循环结束后手动给b的末尾赋值'\0'。
修复后的可正常运行参考代码:
# include <stdio.h> int main(void) { char a[]="0123456789"; char b[6]; // 长度设为6,预留1字节存终止符 a[5]='\0'; char *c=a; // 修正偏移为i避免越界,循环长度减1留位置给终止符 for(int i=0,j=sizeof(b)/sizeof(char) - 1;i<j;i++){ *(b+i)=*(c+i); } b[5] = '\0'; // 手动补字符串结束符 printf("%d\n", (int)(sizeof(a)/sizeof(char))); // sizeof返回size_t类型,强转int避免格式警告 printf("%s\n", a); printf("%s\n", b); printf("%c\n", *(b+3)); return 0; }
运行后正常输出4项结果:
11 01234 01234 3
如果你的预期逻辑不是顺序读取a的字符,只要保证偏移量不超过a的最大合法下标、b数组正确添加'\0'终止符,就不会再出现输出缺失的问题。
内容的提问来源于stack exchange,提问作者Hallo
相关产品推荐
相关产品推荐

