碧海潮生님의 프로필碧海潮生的小屋사진블로그리스트 도구 도움말
    10월 6일

    C语言专题——整型升级和寻常算术转换

    ANSI C中的整型升级

    char,short int或者int型位段(bit-field),包括它们的有符号或无符号变型,
    以及枚举类型,可以使用在需要int或unsigned int的表达式中,
    如果int可以完整地表示源类型的所有值,那么该类型的值就转换为int,否则转换为unsigned int。

    ANSI C中的寻常算术转换

    当执行算术运算时,操作数的类型如果不同,就会发生转换。
    数据类型一般朝着浮点精度更高、长度更长的方向转换,
    整型数如果转换为signed不会丢失信息,就转换为signed,否则就转换为unsigned。
    这个称为值保留(value preserving)原则,与K&R C所采用的无符号保留(unsigned preserving)原则不同。

    int d = -1;
    if (d <= sizeof(arr)/sizeof(arr[0]))
     ...
    这样的比较语句有问题,sizeof运算符返回无符号数。
    if语句在signed int和unsigned int之间测试相等性,
    按照上面的说法,可以这样解释:
    首先,signed int和unsigned int长度相同,不会向更长的方向转换。
    其次,signed int不能完整地表示unsigned int的所有值。
    因此,signed int d被转换为unsigned int类型。
    这样,-1就变成一个非常巨大的正整数,导致比较结果与预期的不符。

    解决的方法是使用强制转换,(int)(sizeof(arr)/sizeof(arr[0]))。
    我在VC++ 6.0和DEV-C++ 4.9.9.0中尝试了上面那段代码,的确如此。

    不要因为无符号数不存在负值而用它表示数量(如年龄、国债等),
    尽量使用int之类的有符号数,这样在混合运算中,
    这样就不必担心边界情况(如-1被翻译为非常大的正数)。

    只有在使用位段和二进制掩码时,才使用无符号数。
    应该在表达式中使用强制类型转换,使所有的操作数均为有符号数或无符号数,
    这样就不必由编译器来选择结果的类型。
     
    C语言中的类型转换比一般人想象中的要广泛得多。
    在涉及类型小于int或double的表达式中,都有可能出现类型转换。

    printf(" %d ", sizeof 'A');
    的结果是4, 是int的长度。

    整型提升就是char、short int和位段类型(无论signed或unsigned)以及枚举类型将被提升为int,
    前提是int 能够完整地容纳原先的数据,否则将被转换为unsigned int。

    ANSI C表示,如果编译器能够保证运算结果一致,
    也可以省略类型提升——这通常出现在表达式中存在常量操作数的时候。

    另一个会发生隐式类型转换的地方就是参数传递。
    在K&R C中,由于函数的参数也是表达式,所以也会发生类型提升。
    在ANSI C中,如果使用了适当的函数原型,类型提升便不会发生,否则也会发生。
    在被调用函数的内部,提升后的参数被裁减为原先声明的大小。

    这就是为什么单个的printf()格式字符串%d能适用于几个不同类型,
    short、char或int,而不论实际传递的是上述类型的哪一个。
    函数从堆栈中(或寄存器中)取出的参数总是int类,并在printf或其他被调用函数里按统一的格式处理。
    printf是一个可变参数函数,此时一般的参数提升始终会发生。
     
    原型之痛

    ANSI C函数原型的目的是使C语言成为一种更加可靠的语言。
    建立原型就是为了消除形参和实参之间的类型不匹配。

    如果使用了函数原型,缺省参数提升就不会发生。
    如果参数声明为char,则实际传递的也是char。
     
    如何进行强制类型转换,为何要进行类型强制转换

    “强制类型转换(cast)”这个术语从C语言一诞生就开始使用,
    既用于“类型转换”,也用于“消除类型歧义”。

    (float)3 是一个类型转换,而且数据的实际二进制位发生了改变,
    (float)3.0 用于消除类型歧义,这样编译器可以从一开始就选择正确的位模式。

    有些人认为它之所以命名为强制类型转换是因为它们可以把有些东西变得不完整。
     
    source: 《Expert C Programming》

    댓글

    잠시만 기다려 주세요...
    죄송합니다. 입력한 댓글이 너무 깁니다. 내용을 줄여 보세요.
    입력한 내용이 없습니다. 다시 시도해 보세요.
    죄송합니다. 지금은 댓글을 추가할 수 없습니다. 나중에 다시 시도해 보세요.
    댓글을 추가하려면 부모님의 사용 허락이 필요합니다. 허용 요청
    부모님이 댓글 기능을 해제한 상태입니다.
    죄송합니다. 지금은 댓글을 삭제할 수 없습니다. 나중에 다시 시도해 보세요.
    하루에 남길 수 있는 댓글의 최대 한도를 초과했습니다. 24시간 후에 다시 시도해 보세요.
    회원님의 계정은 다른 사용자에게 스팸 메일을 보낼 수 있다고 여겨지므로 댓글 기능이 비활성화되어 있습니다. 이 설정에 문제가 있다고 생각되면 Windows Live 지원에 문의하시기 바랍니다.
    댓글을 남기려면 아래 보안 검사를 완료해야 합니다.
    보안 검사에 입력한 글자는 그림 또는 오디오에 있는 글자와 일치해야 합니다.

    댓글을 추가하려면 Windows Live ID로 로그인하세요. 핫메일, 메신저 또는 Xbox LIVE를 사용하는 경우 해당 계정을 Windows Live ID로 사용할 수 있습니다.로그인


    Windows Live ID가 없으신가요? 등록

    트랙백

    이 블로그의 트랙백 URL은 다음과 같습니다.
    http://jx-kingwei.spaces.live.com/blog/cns!F7A152EB74B9576E!721.trak
    이 블로그를 참조하는 웹 로그
    • 없음