9

几个是大多C语言初学者都会迷惑的问题

 3 years ago
source link: https://blog.popkx.com/several-are-confusing-questions-for-most-beginners-of-c/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

几个是大多C语言初学者都会迷惑的问题

发表于 2019-02-05 20:02:44   |   已被 访问: 414 次   |   分类于:   C语言   |   暂无评论

绝大多数C语言编程教材在介绍到数组时都会提到:数组下标是从 0 开始编号的,使用数组时一定不能超出定义的元素个数。这当然没什么好说的,初学者看到这句话,一般都会遵守。

48e1b32ecdf6a714812b4a49a5c82d44.png

奇怪的C语言数组

不过,总有人乐意折腾,小明发现在C语言编程里定义了数组后,使用数组即使超出了最大的元素个数,也能得到正确的结果,他的 C 语言代码是下面这样的:

#include <stdio.h>
int main()
 {
     int a[5] = {0};
     int i;

     for(i=1; i<=5; i++)
         a[i] = i*2; 
     for(i=1; i<=5; i++)
         printf("a[%d] = %d\n", i, a[i]);
     return 0;
}
f771c32c632085c9eada77d8b1d81eb9.png

以上 C 语言代码编译后,运行结果如下:
# ./a.out 
a[1] = 2
a[2] = 4
a[3] = 6
a[4] = 8
a[5] = 10

这样的结果让小明困惑不已,到底是为什么呢?现在我们将C语言比作“一位仁慈的皇帝”,它赏赐给了每一个王爷(进程)一块领地(内存)。王爷如何管理领地,皇帝就不管了,但是每一个王爷都不能侵犯别人的领地(进程不能直接使用别的进程内存),否则就杀死侵犯者(进程引用非法指针会引发“段错误”,进程就死(退出运行)了)。

王爷有感于皇帝的仁慈,颁布了如下法令:在本王领地里,臣民们可以自由使用土地。这条法令其实已经可以解答小明的困惑了,臣民 a 去王府登记,领了 5 亩地,a 自然可以使用 a[0] 到 a[4] 这 5 亩地。

71985bcecf5720884b1b2e6945f3f232.png

臣民 a 真的可以随意使用土地吗?

但是现在王国里只有 a 一个人,所以其它土地暂时都是无主的,按照法令,“臣民们可以自由使用土地”,所以 a 使用 a[5] 这块无主地,王爷也是不管的。那 a 就嚣张了,它还使用了 a[6] 到 a[10] 这几块地,请看如下C语言代码:

 #include <stdio.h>
int main()
 {
     int a[5] = {0};
     int b[10] = {0};
     int i;
     for(i=1; i<=10; i++)
         a[i] = i*2; 
     for(i=1; i<=10; i++)
         printf("a[%d] = %d\n", i, a[i]);
     return 0;
 } 
504a4c338d3c39bc4087905e9a325438.png

编译执行,得到如下结果:
# ./a.out 
a[1] = 2
a[2] = 4
a[3] = 6
a[4] = 8
a[5] = 10
a[6] = 12
a[7] = 14
a[8] = 16
a[9] = 18
a[10] = 20

似乎一切都很正常。细心的朋友应该能够看到,王国里又来了新居民 b,它去王府登记,打算申请 10 亩地种玉米。王府查了登记簿,发现之前只有 a 申请了 5 亩地,所以就把 a 旁边的 10 亩地分配给了 b。拿到地的 b 高高兴兴的把地犁了一遍(int b[10] = {0};),打算种玉米。现在,我们将C语言代码稍作修改,把 b 的土地情况也打印出来:

// 将
printf("a[%d] = %d\n", i, a[i]);
// 修改为
printf("a[%d] = %d, b[%d] = %d\n", i, a[i], i-1, b[i-1]);

再编译C语言程序,运行结果如下:

9e6ba622712d417c2771b0b81c4190e6.png

b 辛辛苦苦犁好的地,就这么被 a 种上它自己的东西了。其实出现这种情况,从某种程度上来说也是必然的。想想看,a 使用了 a[5] 到 a[10] 这些无主地时,并没有去王府登记,所以王府根本不知道 a 使用了这些地。当居民 b 来申请土地时,非常有可能把这些土地分配给 b。这就导致了冲突。

现在已经能够解答小明的困惑了:C语言是一门非常自由的语言,它给了程序员最大的自由,它相信每个C语言程序员都是高手,都知道自己在做什么,在C语言中,高手们使用 p[-1] 这种访问数组元素的方式也并不是没有。

现在来考虑 a 和 b 的冲突:如果 a 和 b 私下商量好,b 愿意把自己的一部分土地让给 a 使用,那即使冲突也没有什么问题,王国内依然一派和气。

ea3f82d6756071c35d35d9c26aa206b2.png

但是仍然不建议像 a 那样霸道的使用别人的土地,因为很难遇到像 b 这么好说话的居民。另外,假如皇帝要求王爷进贡 10 亩玉米,王爷查看土地登记簿,发现 b 已经申请了 10 亩土地种玉米,就放心了。结果,b 的一部分土地被 a 拿去种别的东西了,导致王爷无法完成皇帝的任务被杀头,整个王国就都完蛋了。

阅读更多:   C语言


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK