前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你真的会 C 语言吗

你真的会 C 语言吗

作者头像
SuperFeng
发布2019-09-26 16:17:25
9890
发布2019-09-26 16:17:25
举报
文章被收录于专栏:SuperFengSuperFeng

身为一名程序员,或多或少都会了解一点 C 语言,我现在还清楚地记得,大一刚接触 C 语言时被它所支配的恐惧。C 语言无比强大,被称为「高级汇编语言」足以见得它的威力,也可以看出它经常与计算机底层打交道;它的指针部分更为精彩(也是最难的部分),那么我们就跳过它最难的部分,检查一下你对 C 语言掌握的程度。

下面是一个函数 sum_elements( ),它的作用是对给定的数组中所有元素求和并返回其值,按照代码中给定的值去执行,你认为会得到什么结果呢?

#include<stdio.h>


float sum_elements(float a[], unsigned length) {
    int i;
    float result;

    result = 0;
    for (i = 0; i <= length - 1; i++)
        result += a[i];

    return result;
}

void main()
{
    float a[1] = { 0.1 };
    float sum;

    sum = sum_elements(a, 0);
    printf("%f\n", sum);
}

当我们让 length = 0 时,想要得到的结果是 0.000000,但是运行时你会发现该程序会报出内存访问异常错误。你知道是什么原因出现这个错误吗?这就是检验你功底是否扎实的时候了,先仔细看看代码,好好想一想再继续往下看。

... ...

怎么样,知道是什么原因导致这段代码出现了我们预料之外的错误了吗?这里的 bug 是无符号整数(unsigned)导致的。

在 C 语言中,无符号整数是 4 个字节,1 个字节为 8 位,十进制数 0 用二进制表示为 0000 0000 0000 0000 0000 0000 0000 0000,计算机做减法是通过补码进行,补码为源码除符号位外各位取反再加一。-1 的补码为 1111 1111 1111 1111 1111 1111 1111 1111,计算 length - 1 (0 - 1) 就是求 length 与 -1 的补码之和,得到的结果为 1111 1111 1111 1111 1111 1111 1111 1111,因为之前定义形参的时候将 length 定义为无符号整数,所以 C 语言将计算结果按照无符号整数解释,得到的十进制数字为 4294967295(2^32 - 1)而不是我们想要的 -1,循环时 i 初值被赋为 0 ,一直小于这个数,所以循环会不断地进行,代码将试图访问数组 a 的非法元素,导致内存访问异常。

这个程序表面上一切正常,很符合正常人思路,数组下标不能为负数,因此形参 length 用无符号整数表示;停止条件 i <= length - 1 看上去也十分自然。但是将这两个条件组合在一起,意料之外的事情就发生了。C 语言确实很强大,但是如果我们的计算机基础知识不扎实,很可能出现各种奇奇怪怪的 bug。原来我一直觉得学那些枯燥无味的计算机基础知识没用,但是越往前走越发觉计算机基础知识很重要。书到用时方恨少,出了 bug 找不到

现在这个 bug 的原因已经找到了,如何修改这个 bug 使得该程序能够顺利执行呢?有想法的小伙伴可以在文章下方留言区告诉我你的想法哦。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SuperFeng 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档