那些与size

    xiaoxiao2021-03-25  104

    早上来到实验室就开始debug,于是再一次看到了自己的愚蠢,size_t在一旁冷笑:“小样儿!你以为你很懂我……”最近总是发现一些很低级的bug,一来是由于自己的粗心,二来是由于自己的不细心。下面先记下最近遇到的两个与size_t相关的bug,以后遇到了再更新。不过还是希望再也不要遇到……


    1. size_t与int做减法溢出

    int minnum = 2; int maxnum = 12; string Seq = "ABCDEFGHIJ"; // length = 10 for (int j = Seq.length() - minnum - 1; j >= 0 && j >= Seq.length() - maxnum; --j){ printf("+ %c\n", Seq[j]); }

    我本以为以上代码会输出前8个字符,然而却一个也没有输出。反复检查了好多遍,都觉得代码没毛病。既然都没有进入到循环里面,那么我倒想看看循环停止条件是如何被满足的:

    cout << Seq.length() - minnum - 1 << ", " << (Seq.length() - maxnum) << endl;

    输出结果让人醍醐灌顶: 前面的10-2-1=7没问题,后面的Seq.length() - maxnum = 10 - 12 = 4294967294 ? 天啊,我竟然忘记了Seq.length()的返回类型是size_t,也就是unsigned int。当从无符号数中减去一个数时,不管这个值是不是无符号数,我们都必须确保结果不可能是负数。因此当10-12=-2时,-2会被转化成无符号数4294967294,它们在内存中的编码方式是一样的,只是解析方式不同。下面我们来看一下完整的测试和输出,就可以一目了然了:

    void test2() { int minnum = 2; int maxnum = 12; string Seq = "ABCDEFGHIJ"; for (int j = Seq.length() - minnum - 1; j >= 0 && j >= Seq.length() - maxnum; --j){ printf("+ %c\n", Seq[j]); } cout << Seq.length() - minnum - 1 << ", "; cout << (Seq.length() - maxnum) << " = " << hex << Seq.length() - maxnum << endl; for (int j = Seq.length() - minnum - 1; j >= 0 && j >= (int)Seq.length() - maxnum; --j){ printf("- %c\n", Seq[j]); } }

    输出如下:

    总之,切勿混用带符号类型和无符号类型。如果表达式里面既有带符号类型,又有无符号类型,当带符号类型取值为负时,会出现异常结果,这是因为带符号数会自动转化为无符号数。

    2. for循环中循环变量自减溢出

    下面这个错误是前几天犯的,比较low,但也比较常见。

    for(size_t i=5; i>=0; --i){ cout << i << endl; }

    这个循环你以为会正常退出吗?然而却陷入了死循环。道理是一样的,只因为size_t是unsigned int。当i等于0时,继续执行for语句中的自减操作,得到的结果-1并不满足无符号数的要求,此时像所有表示范围以外的数一样,-1会被自动转化为合法的无符号数。假设int型为32位的话,则当i=0时,–i的结果将会是4294967295。

    看来我们需要时刻记得size_t的身份,丝毫不能越矩,否则就会受到惩罚。

    转载请注明原文地址: https://ju.6miu.com/read-21800.html

    最新回复(0)