为何这段C语言代码能正确打印字符串?逻辑疑问求解
关于这段C语言代码的错误分析
首先明确:这段代码存在严重的数组越界问题,你测试时得到“正确”结果只是巧合,属于未定义行为,绝对不能这么写。下面逐个解释你的疑问:
1. 为什么scanf("%s", &flower[i][50])能“正常工作”?
char flower[7][50]是一个7行50列的二维字符数组,内存中是连续存储的:第0行从flower[0][0]到flower[0][49],紧接着是第1行flower[1][0]到flower[1][49],以此类推。- 正确的写法应该是
scanf("%s", flower[i])或者scanf("%s", &flower[i][0]),这两个表达式等价,都是第i行的起始地址,用来存储第i+1个输入的花名(因为循环i从0开始)。 - 而
&flower[i][50]是第i行第50个元素的地址——注意每行只有50个元素,索引是0到49,所以这个地址其实就是第i+1行的起始地址。 - 循环中i从0到6:
- i=0时,写入
flower[1]的位置; - i=1时,写入
flower[2]的位置; - ...
- i=5时,写入
flower[6]的位置; - i=6时,
&flower[6][50]已经超出了flower数组的内存范围(数组只有7行,索引0-6),属于越界写入,这是未定义行为——可能覆盖其他变量、导致程序崩溃,只是你的测试环境没触发而已。
- i=0时,写入
2. 为什么printf用n而非n-1能得到正确结果?
这完全是前面越界写入导致的错位巧合:
- 正常逻辑下,用户输入的n是“第n个花”,对应数组索引应该是
n-1(因为数组从0开始)。 - 但因为前面的
scanf把第1个输入的花名写到了flower[1],第2个写到flower[2]……第6个写到flower[6],所以当你输入n=6时,访问flower[6]刚好是第6个输入的内容,看起来正确。 - 如果输入n=1,访问
flower[1]也会得到第1个输入的花名,但这都是错误代码带来的假象,一旦数组越界的内存被其他变量占用,程序立刻会出问题。
修正后的正确代码
char flower[7][50]; int i, n; for (i = 0; i < 7; i++) { printf("Enter the name of the flower number %d : ", i + 1); scanf("%s", flower[i]); // 或者&flower[i][0],两者等价 } printf("\nEnter the number of the flower you want : "); scanf("%d", &n); // 这里要注意判断n的范围,避免越界访问 if (n >= 1 && n <=7) printf("Flower number %d is %s\n", n, flower[n-1]); else printf("Invalid flower number!\n");
内容的提问来源于stack exchange,提问作者PhoenXHO
相关产品推荐
相关产品推荐

