zoukankan      html  css  js  c++  java
  • char/unsigned char对比较结果的致命影响

    一、字符符号
    这个问题以前知道char类型有默认有符号和无符号的区分,但是这两种区分到底有什么区别,概念还是比较模糊的,直到今天因为字符符号搞了一个大乌龙,搞的版本无法启动,才算是有了一次刻骨铭心的认识。
    二、比较语句
    下面是比较的一个模型,gcc中,char类型在i386/MIPS体系结构默认是有符号的,而PowerPC/ARM是无符号的。现在看一个比较指令
    int foo(char cond)
    {
      return cond == 0xCC;
    }
    这个现在假设char传入的值为0xCC,此时这个函数返回值是多少呢?非常惊讶的是,返回值为0,事实上这是一个恒为0的函数,在fedora core上编译该文件
    [root@Harry falsealways]# cat falsealways.c
    int foo(char cond)
    {
        return cond == 0xcc;
    }
    [root@Harry falsealways]# gcc -c falsealways.c -Wall
    [root@Harry falsealways]# objdump -d falsealways.o

    falsealways.o:     file format elf32-i386


    Disassembly of section .text:

    00000000 <foo>:
       0:    55                       push   %ebp
       1:    89 e5                    mov    %esp,%ebp
       3:    83 ec 04                 sub    $0x4,%esp
       6:    8b 45 08                 mov    0x8(%ebp),%eax
       9:    88 45 fc                 mov    %al,-0x4(%ebp)
       c:    b8 00 00 00 00           mov    $0x0,%eax  这里返回值始终为0,也就是无论你传入什么值,这个函数都只会返回零,这个返回值在编译时就确定了
      11:    c9                       leave  
      12:    c3                       ret    
    [root@Harry falsealways]# gcc -v
    Using built-in specs.
    Target: i686-redhat-linux
    Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
    Thread model: posix
    gcc version 4.4.2 20091027 (Red Hat 4.4.2-7) (GCC) 
    三、gcc是怎么看这个问题的
    对于 
    cond == 0xCC;
    更为清楚的表达为
    (char)cond == 0x000000CC;
    也就是说,这个0xcc你看起来是一个字符常量,事实上他是一个整数常量,占用4个字节,所以char类型要向它看齐,从char拔高到int。

    1、假设传入的cond值为负数,在进行带符号扩展时,最高3byte全部补充为0xFF,即为0xFFFFFFFXX,由于高3bytes和常量0x000000CC的对应值不同,所以两个值肯定不同;
    2、假设cond的值为正值,那么它作为char的最高bit,也就是从右向左的第八bit为0,而常量0x000000cc的第八bit为1,所以也不可能相等。

    但是等一下,在4.1编译器中这里还会给一个警告,为什么这个坑爹的4.4即使加了Wall选项还是没有呢?
     
     
     
     
     
  • 相关阅读:
    常用jquery
    常用记录
    mysql proxy 读写分离
    Linux 学习笔记
    php 1116
    php 1115
    php 1110
    php 1109
    php 1108
    php 1105
  • 原文地址:https://www.cnblogs.com/tsecer/p/10486095.html
Copyright © 2011-2022 走看看