登录C扩展 [英] sign extension in C

查看:104
本文介绍了登录C扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我期待在这里了解符号扩展:
http://www.shrubbery.net/solaris9ab/SUNWdev/SOL64TRANS/p8.html

结构foo的{
        无符号整型基地:19,老调重弹:13;
    };    主(INT ARGC,CHAR *的argv [])
    {
        结构foo的;
        无符号长地址;        a.base = 0x40000;
        地址= a.base<< 13; / *符号扩展在这里! * /
        的printf(地址为0x%LX \\ n,地址);        地址=(unsigned int类型)(a.base<&; 13); / *无符号扩展在这里! * /
        的printf(地址为0x%LX \\ n,地址);
    }

他们声称这样的:

------------------ 64位:

 %CC -o test64 -xarch = V9 test.c的
%./test64
地址0xffffffff80000000
地址为0x80000000

------------------ 32位:

 %CC -o test32 test.c的
%./test32
地址为0x80000000
地址为0x80000000

我有3个问题:


  1. 什么是符号扩展?是的,我读维基,但在类型提升时,这是怎么回事带符号扩展?不明白

  2. 为什么FFFF。在64位(指地址)?

  3. 当我做类型转换,为什么没有符号扩展?

编辑:
4.为什么不是在32位系统的问题?


解决方案

  a.base<< 13

该位运算符对两个操作数执行整型的提升。

因此​​,这等同于:

 (INT)a.base<< 13

这类型的负值 INT

然后:

 地址=(int)的a.base<< 13;

转换此签署负值((INT)a.base<&; 13 ),以类型地址无符号长通过整数转换。

整数转换(C99,6.3.1.3p2)规则是相同的操作的方式:

 地址=(长)((INT)a.base<&; 13);

转换在这里进行符号扩展,因为((int)的a.base<< 13)是一种消极的符号数。

在其他情况下,与投你要什么当量:

 地址=(无符号长)(无符号整数)(INT)a.base&LT(;&; 13);

所以没有符号扩展是你的第二个案例进行的,因为(无符号整数)((int)的a.base<< 13)是一个无符号(和积极的当然)值。

修改:与 KerrekSB 的在他的回答 A提及。基地<< 13 是实际上不会再presentable一个 INT (我假设的32位 INT ),所以这个前pression调用未定义的行为,并实施了他的权利以任何其他方式表现,例如崩溃。

有关信息,这绝对不是移植,但如果您使用的是 GCC GCC 不考虑 a.base<< 13 这里为未定义行为。从 GCC 文件:


  

GCC不使用C99给出的纬度唯一治疗签订某些方面'<<'未定义,但这可能会改变。


http://gcc.gnu.org/onlinedocs/gcc/Integers -implementation.html

I'm looking here to understand sign extension: http://www.shrubbery.net/solaris9ab/SUNWdev/SOL64TRANS/p8.html

    struct foo {
        unsigned int    base:19, rehash:13;  
    };

    main(int argc, char *argv[]) 
    {
        struct foo  a;
        unsigned long addr;

        a.base = 0x40000;
        addr = a.base << 13;        /* Sign extension here! */
        printf("addr 0x%lx\n", addr);

        addr = (unsigned int)(a.base << 13);  /* No sign extension here! */
        printf("addr 0x%lx\n", addr);
    }

They claim this:

------------------ 64 bit:

% cc -o test64 -xarch=v9 test.c
% ./test64
addr 0xffffffff80000000
addr 0x80000000
%

------------------ 32 bit:

% cc -o test32 test.c
% ./test32
addr 0x80000000
addr 0x80000000
%

I have 3 questions:

  1. What is sign extension ? Yes I read wiki, but didn't understand when type promotion occurs, what's going on with sign extension?
  2. Why ffff.. in 64 bit(referring addr) ?
  3. When I do type cast, why no sign extension?

EDIT: 4. Why not an issue in 32 bit system?

解决方案

a.base << 13

The bitwise operator performs integer promotions on both its operands.

So this is equivalent to:

    (int) a.base << 13

which is a negative value of type int.

Then:

addr = (int) a.base << 13;

converts this signed negative value ((int) a.base << 13) to the type of addr which is unsigned long through integer conversions.

Integer conversions (C99, 6.3.1.3p2) rules that is the same as doing:

addr = (long) ((int) a.base << 13);

The conversion long performs the sign extension here because ((int) a.base << 13) is a negative signed number.

On the other case, with a cast you have something equivalent to:

addr = (unsigned long) (unsigned int) ((int) a.base << 13);

so no sign extension is performed in your second case because (unsigned int) ((int) a.base << 13) is an unsigned (and positive of course) value.

EDIT: as KerrekSB mentioned in his answer a.base << 13 is actually not representable in an int (I assume 32-bit int) so this expression invokes undefined behavior and the implementation has he right to behave in any other way, for example crashing.

For information, this is definitely not portable but if you are using gcc, gcc does not consider a.base << 13 here as undefined behavior. From gcc documentation:

"GCC does not use the latitude given in C99 only to treat certain aspects of signed '<<' as undefined, but this is subject to change."

in http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

这篇关于登录C扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆