zoukankan      html  css  js  c++  java
  • C语言陷阱——类型转换

     以下例子取自《深入理解计算机系统》。

     考虑如下的C语言代码:

     1 #include<stdio.h>
     2 
     3 typedef unsigned char* byte_pointer;
     4 
     5 void show_bytes(byte_pointer pointer, int size){
     6     int i = 0;
     7     for (i = 0; i < size; ++i){
     8         printf("%.2x", pointer[i]);
     9     }
    10 }
    11 
    12 int main(){
    13     short sx = -12345;
    14     unsigned uy = sx;
    15     printf("uy = %u:\t", uy);
    16     show_bytes((byte_pointer)&uy, sizeof(unsigned));
    17     printf("\n");
    18 }

    该程序在小端法的机器上会产生如下输出:uy = 4294954951:        c7cfffff

    这表明当把short转换成unsigned 时,我们先改变大小,之后在完成从有符号到无符号的转换。也就是说(unsigned)sx等价于(unsigned)(int)sx,求值得到4294954951,而不等价于(unsigned)(unsigned short)sx,后者求值得到53191。事实上,这个规则是C语言标准要求的。

    另外,当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式地将有符号参数强制类型转换为无符号参数,并假设这两个数都是非负的,来执行这个运算。这种方法对于标准的算数运算并无多大差异,但是对于<和>这样的关系运算符来说,它会导致非直观的结果。

    例如对(-1 < 0U)这个表达式求值,其结果为0。因为第二个运算数是无符号的,第一个运算数会被隐式地转换为无符号数,因此表达式就等价为(4294967295U < 0U),这个答案显然是错的。

    基于同样的理由,我们考虑一下代码:

    1 double sum_elements(double a[], unsigned length){
    2     int i;
    3     double result = 0;
    4     for (i = 0; i <= length - 1; ++i){
    5         result += a[i];
    6     }
    7     return result;
    8 }

    当传入的length=0时,会产生越界错误。

  • 相关阅读:
    codevs 3160 最长公共子串
    bzoj1593 [Usaco2008 Feb]Hotel 旅馆
    bzoj1230 [Usaco2008 Nov]lites 开关灯
    洛谷P1558 色板游戏
    洛谷P2253 好一个一中腰鼓!
    洛谷P2345 奶牛集会
    TopCoder SRM420 Div1 500pt RedIsGood
    洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm_Silver
    洛谷P1455 搭配购买
    洛谷P2398 GCD SUM
  • 原文地址:https://www.cnblogs.com/fuji/p/4713159.html
Copyright © 2011-2022 走看看