zoukankan      html  css  js  c++  java
  • 默认参数提升

    在C语言中,调用一个不带原型声明的函数时:调用者会对每个参数执行“默认实际参数提升(default argument promotions)。

    同时,对可变长参数列表超出最后一个有类型声明的形式参数之后的每一个实际参数,也将执行上述提升工作。

    提升工作如下:
    ——float类型的实际参数将提升到double
    ——charshort和相应的signed、unsigned类型的实际参数提升到int
    ——如果int不能存储原值,则提升到unsigned int

    /***************************************************************/
    int main()
    {
    int i;
    unsigned char *p;
    char *p1;
    int a[] = {0xffffffff, 0xffffffff, 0xffffffff};
     
    p = a;
    p1 = a;
    for(i = 0 ; i < 8 ; i++) {
    printf(" 0x%02x  0x%02x ", p[i], p1[i]);
    }
     
    }
    $ gcc main.c 
    main.c: In function ‘main’:
    main.c:10: warning: assignment from incompatible pointer type
    main.c:11: warning: assignment from incompatible pointer type
    $ ./a.out 
     0xff  0xffffffff 
     0xff  0xffffffff 
     0xff  0xffffffff 
     0xff  0xffffffff 
     0xff  0xffffffff 
     0xff  0xffffffff 
     0xff  0xffffffff 
     0xff  0xffffffff 
    。。。。。。 。。。。。。
    /***************************************************************/
     
    根本原因其实很简单。
    %x是打印无符号整数的16进制,而例子中传递的类型是字符型,那么这里就有一个字符提升的问题,将类型提升为无符号整形。
    *p是unsigned char,其值为0xff,那么对应的无符号整形的值仍然是0xff。
    而*p1确实char,其值为0xff,其对应的无符号整形的值为0xffffffff。为什么这次是0xffffffff呢?
    因为*p1为-1,而无符号整数的-1则是0xffffffff。
     
    为什么是这样呢?
    因为在在编码为补码的情形下,类型提升有两种情况:
    1. 符号扩展:对于有符号数,扩展存储位数的方法。在新的高位字节使用当前最高有效位即符号位的值进行填充。
    2. 零扩展:对于无符号数,扩展存储位数的方法。在新的高位直接填0.
     
    对于这个例子来说。*p是无符号数,所以填充的是0,即为0x000000ff。而*p1是有符号数,所以填充的是1,即为0xffffffff。
     
    因此,从char型到unsigned int,是对有符号数的提升,因此用的是符号扩展,oxff被扩展为oxffffffff;而从unsigned char型到unsigned int型,是对无符号数的扩展,使用零扩展,oxff被扩展为ox000000ff,而填充的这些零是不会被打印出来的。
     
    如果说这样教科书式的概念不容易理解。还有这样一种理解方式,也许不一定准确,但更容易理解。
    对于这里的类型提升,整个步骤可以这样理解:
    1. %x要求参数为无符号整数,需要参数为4个字节;
    2. *p, *p1为(unsigned) char型,只占1个字节;
    3. 因为参数的类型不符,需要扩展;
    4. 定位需要扩展到4个字节;
    5. 那么就需要填充增加的3个字节;
    6. 这3个字节需要什么值?这里就需要上面所需要的概念了。针对有符号数和无符号数,进行不同值的填充。

    详见

    C语言可变长参数函数与默认参数提升

    C语言可变参数函数取参方法

    编写安全代码:关于整数提升 

    C语言中的类型提升——基础概念,但还有很多人搞不清 

  • 相关阅读:
    Java web错误汇总
    JSP自学笔记
    猜拳游戏三局两胜------java实现代码
    Exception异常处理
    XDocument简单入门
    使用oledb读取excel表
    ueditor 定制工具栏图标
    在mvc返回JSON时出错:序列化类型为“System.Data.Entity.DynamicProxies.Photos....这个会的对象时检测到循环引用 的解决办法
    在网页中浏览PDF文档
    Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)
  • 原文地址:https://www.cnblogs.com/zhanbiqiang/p/4009043.html
Copyright © 2011-2022 走看看