C语言循环中字符数组元素值异常变更原因咨询
字符形式整数相加时数组越界导致的问题解析
问题背景
我在完成C语言作业时需要实现字符形式的整数相加(比如"123"和"321"相加得到"444"),思路是通过计算字符与'0'的ASCII差值转成数值后运算。但写代码时用char total[] = { 0 };定义数组,循环里发现total[1]的值从'4'莫名变成\x01,改成char total[4] = { 0 };后问题就解决了,想知道原写法失效的原因。
相关代码
#include <stdio.h> int main (int argc, char *argv[]) { char *num1 = "123"; char *num2 = "321"; const char Z = 48; //value of zero char from_z = 0; char total[] = { 0 }; int i = 0; //main for loop for (i = 0; num1[i] != '\0' || num2[i] != '\0'; i++) { from_z = num2[i] - Z; //distance from '0' total[i] = num1[i] + from_z; //print out contents of current index and previous //to compare printf("i total[%d]: %c\n", i, total[i]); printf("i - 1: total[%d]: %c\n", i-1, total[i-1]); } printf("i: %d\n", i); total[i] = '\0'; return 0; }
运行输出
i total[0]: 4 i - 1: total[-1]: i total[1]: 4 i - 1: total[0]: 4 i total[2]: 4 i - 1: total[1]: i: 3
问题根源:数组越界与未定义行为
- 当你用
char total[] = { 0 };定义数组时,编译器会根据初始化列表的元素数量确定数组大小——这里只初始化了一个元素,所以total是长度为1的char数组,仅能合法访问total[0]。 - 你的循环会执行3次(i从0到2),循环结束后还会执行
total[3] = '\0',这意味着你连续访问了total[1]、total[2]、total[3],这些都是数组边界外的内存区域。 - C语言不会自动检查数组越界,访问超出数组范围的内存属于未定义行为:这部分内存可能是其他变量的存储空间,也可能是栈上的其他数据,写入操作会破坏这些未知内容,导致之前写入的
total[1]被意外覆盖(比如被循环变量i的更新、printf的栈操作等改写),就出现了你看到的total[1]值莫名变化的情况。 - 改成
char total[4] = { 0 };后,数组长度足够容纳3位结果字符加上末尾的终止符'\0',所有访问都在合法范围内,未定义行为消失,问题自然解决。
补充说明
代码里还有个潜在问题:当循环到i=3时,num1[i]和num2[i]都是字符串终止符'\0',此时num2[i] - Z会计算成'\0' - 48(即-48),虽然这里循环结束后直接给total[3]赋值'\0'覆盖了,但如果是更长的字符串或者逻辑变化,可能会引发其他问题,建议在循环里判断字符是否为'\0',如果是就按0处理。
内容的提问来源于stack exchange,提问作者AsianDora
相关产品推荐
相关产品推荐

