碧海潮生's profile碧海潮生的小屋PhotosBlogLists Tools Help

碧海潮生的小屋

大江大水天自高 轻舟穿江两岸 笑看山河绕
Photo 1 of 10

碧海潮生 Kingwei

Windows Media Player

November 07

图+名章

October 01

巴黎即景

 
 
 
 
 
 
 
 
 
July 15

RHEL5 64bit下的数据类型及其转换

环境: gcc 4.1.2 20080704 (Red Hat 4.1.2-44), 使用-Wall编译选项

1. 基本数据类型小结
基本类型包括字节型(char)、整型(int)和浮点型(float/double)。
定义基本类型变量时,可以使用符号属性signed、unsigned(对于char、int),
和长度属性short、long(对于int、double)对变量的取值区间和精度进行说明。
下面列举了rhel5_64bit gcc下基本类型所占位数和取值范围:
 
符号属性      长度属性      基本型     所占位数         取值范围      输入符举例       输出符举例
--            --          char         8         -2^7 ~ 2^7-1        %c          %c、%d、%u
signed        --          char         8         -2^7 ~ 2^7-1        %c          %c、%d、%u
unsigned      --          char         8         0 ~ 2^8-1           %c          %c、%d、%u
[signed]      short       [int]        16        -2^15 ~ 2^15-1              %hd
unsigned      short       [int]        16        0 ~ 2^16-1             %hu、%ho、%hx
[signed]      --           int         32        -2^31 ~ 2^31-1              %d
unsigned      --          [int]        32        0 ~ 2^32-1              %u、%o、%x
[signed]      long        [int]        64        -2^63 ~ 2^63-1              %ld
unsigned      long        [int]        64        0 ~ 2^64-1             %lu、%lo、%lx
[signed]      long long   [int]        64        -2^63 ~ 2^63-1             %lld
unsigned      long long   [int]        64        0 ~ 2^64-1           %llu、%llo、%llx
--            --          float        32       +/- 3.40282e+038         %f、%e、%g
--            --          double       64       +/- 1.79769e+308  %lf、%le、%lg   %f、%e、%g
--            long        double      128       +/- 1.189731e+4932      %Lf、%Le、%Lg
 
Linux采用LP64标准,其中指针和长整数都是64位的,而普通的整数则依然是32位的:
sizeof(long) = 8
sizeof(void *) = 8
无类型的整数常量是int类型的。这可能会导致在位移时出现被截断的问题。
例如,在下面的代码中,a的最大值可以是31(在gcc下实验可知,当a>31时1<<a将进行循环移位而非截断)。
这是因为1<<a是int类型的。
long t = 1 << a;
要在64位系统上进行位移,应该使用1L,如下所示:
long t = 1L << a;
在32位系统上,int和long大小相同。由于这一点,有些开发人员会交换使用这两种类型。
这可能会导致指针被赋值给int类型,或者反之。
但是在64位的系统上,将指针赋值给int类型会导致高32位的值被截断。

2. 整型提升和寻常算术转换
在64位平台上,ANSI标准中的整型提升和寻常算术转换规则依然适用,但多少显得有些令人费解.
Integral promotion
You can use a char, short, enumerated type, or bit-field, whether signed or unsigned,
in any expression that calls for an integer. If an integer can hold all possible values of the original type,
the value is converted to an integer; otherwise, the value is converted to an unsigned integer.
 
注意,整型提升的结果为int/unsigned int,而非long/unsigned long. 如:
sizeof('A') = 4
sizeof(1) = 4
sizeof(1L) = 8
 
即使是向printf这类可变参数函数传递整型参数时,也不会提升为long/unsigned long.
Conversion between signed and unsigned integers
When an integer with a negative sign is promoted to an unsigned integer of the same or larger type,
it is first promoted to the signed equivalent of the larger type, then converted to the unsigned value.
 
举例而言
long n;
int i = -2;
unsigned k = 1;
n = i + k;
1> 因为i和k的类型不一致,进行寻常算术转换
"i" is an integer with a negative sign, it is promoted to an unsigned integer of the same type (unsigned).
于是i变为一个大的正整数0xFFFFFFFE
2> 0xFFFFFFFE和k=1相加,成为0xFFFFFFFF, 类型为unsigned int.
3> 赋值运算符两侧类型不一致,进行寻常算术转换(注意!不是整型提升)
由于中间结果0xFFFFFFFF为无符号数,所以不会进行符号扩展,因此直接添0即得到最终结果
0x00000000FFFFFFFF = 4294967295
 
可见问题出在第1步里,只需将k强制转换为int即可:
n = i + (int)k;
这样运算的中间结果0xFFFFFFFF为有符号数,会进行符号扩展,最终结果为
0xFFFFFFFFFFFFFFFF = -1
 
其实整型间的算术转换令人迷惑的无非是以下四种情况:
情况 \ 平台               ILP32            LP64
int vs. unsigned int   unsigned int   unsigned int
long vs. unsigned long unsigned long  unsigned long
int vs. unsigned long  unsigned long  unsigned long
unsigned int vs. long  unsigned long  long
具体说来,如果一边是无符号数另一边是有符号数, 那么若...
1> 无符号数的Rank不低于有符号数的Rank,则把有符号数转成另一边的无符号类型。
例如unsigned long和int做算术运算时都转成unsigned long,unsigned long和long做算术运算时也都转成unsigned long。
2> 无符号数的Rank低于有符号数的Rank。这时又分为两种情况,如果这个有符号数类型能够覆盖这个无符号数类型的取值范围,
则把无符号数转成另一边的有符号类型。例如LP64的平台上unsigned int和long在做算术运算时都转成long。
3> 否则,也就是这个符号数类型不足以覆盖这个无符号数类型的取值范围,则把两边都转成两者之中较高Rank的无符号类型。
例如ILP32的平台上unsigned int和long在做算术运算时都转成unsigned long。
这个规则比《C Expert Programming》里讲的简单规则准确,也容易记忆。

3. 基本类型特征及扩展数据类型
标准头文件<limits.h>定义了整型特征:
INT_MIN
INT_MAX
SHRT_MIN
SHRT_MAX
USHRT_MAX
LONG_MIN
LONG_MAX
ULONG_MAX
LLONG_MIN
LLONG_MAX
ULLONG_MAX
 
标准头文件<float.h>定义了浮点特性:
FLT_EPSILON
FLT_MIN
FLT_MAX
DBL_EPSILON
DBL_MIN
DBL_MAX
LDBL_EPSILON
LDBL_MIN
LDBL_MAX

标准(ISO C99)库中的扩展类型:
<stddef.h>
typedef long unsigned int size_t;
typedef long int ptrdiff_t;
<signal.h>
typedef int sig_atomic_t;
<time.h>
typedef long int clock_t;
typedef long int time_t;
<wctype.h>
typedef unsigned long int wctype_t;
typedef const signed int *wctrans_t;
<wchar.h>
typedef int wchar_t;
typedef unsigned int wint_t;
<stdint.h>
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
typedef long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
typedef long int intptr_t;
typedef unsigned long int uintptr_t;
 
POSIX库中常用的扩展类型:
typedef int pid_t;
typedef int key_t;
typedef long int ssize_t;
typedef long int off_t;
July 11

[ZT] Top 10 reasons why Pascal is better than C

1. Pascal, noble language as it is, was named after a famous French mathematician and philosopher, Blaise Pascal. C was named after a Sesame Street character.
 
2. Pascal's inventor, Nicholas Wirth, and parameter passing conventions coalesce to form a nifty pun: You can pronounce his name by reference: Wirth or by value: Worth. C was invented at Bell Labs, where they wouldn't know a joke from a transistor.
 
3. There is only one Pascal, as defined by Wirth, while C has (shall we say?) several fathers: Kernighan & Ritchie, Harbison & Steele, Barnum & Bailey, and Laurel & Hardy.
 
4. In C, the following variable names are all different: thesame, TheSame, theSame, and THESAME. Nuff said.
 
5. In Pascal, when you fool with a pointer or handle, you know you're fooling around with a pointer or handle. In C, you could be fooling around with anything. C is the ultimate language for computational promiscuity.
 
6. In Pascal, we *know* how big an integer is.
 
7. C is used by liberal, Democratic, Mike Dukakis types of programmers. Pascal is a favorite of the GOP. Hey, we know what the big language at Berkeley is, don't we?
 
8. C is the only language in the civilized world that still refuses to recognize the $ sign for a hexadecimal constant and continues to promote that base pretender to the throne: 0x00.
 
9. Pascal has well-defined rules for Scope, while C appears to be using Listerine. This accounts for the medicine breath of many C programmers.
 
10. In C, you can do this:
for(;P("\n").R-;P("|"))for(e=3DC;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);
In Pascal, you CAN'T do this :
for(;P("\n").R-;P("|"))for(e=3DC;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);
 
July 10

[ZZ]若你以柔情封起信封

很有感觉的歌词~~
 
写一封信。
用柔软的干净的发黄的素笺。
用削得不尖不细的碳画铅笔。
时间要在秋日的傍晚。
最好是九月。
夕阳刚刚暗去。
晚风静静吹起。
要有细雨呢。
这样子。坐在紫藤花架下。先泡一壶淡茶。心思合着水气,缭缭腾开。
字是不需要写太多。
七十个字吧。
写初见的欢喜。写低眸的相思。写颦眉的暗怨。写心底的温润。
还要写这天气清凉,浮云逶迤,暗香浮动,影月黄昏。
还要写什么呢。
写一朵花,撷在手心,是一缕芬芳,还是满室馨香。
写一个人,站在这里,是站得太晚,还是等得太迟。
还是什么都不需写,对着素笺,浅笑开来。
于是哎,芳草鲜美,落英缤纷。
写吧。要从右写到左。
要从黄昏写到月夜。
然后满天星星都化做云雨,洒落下来。
迷了眼,湿了心。
和着花香水气把信封好。
那些恣意的情绪呵,便随了风,逝去吧。
 

天气预告/访问统计

free web hit counter