1.int n=(-1)&12345
解:12345, -1的二进制是 1111111111111111 (用补码表示,去符号 取反加1)
2.int array[5][3]; array[5]-array[2]=?
解: 9, 数组相减得到的是值的个数,而不是所需要的空间数。空间数是36,一个int/指针占4个字节。
如:
main()
{
int a[5][5];
printf("%d/n",&a[0][1]-&a[0][0]);
}
为什么打印结果是 1 而不是 1*sizeof(int) 呢
答:因为指针的运算都是以一个元素为单位, 整形指针就是以一个整型的长度为单位, 数组也是一样。
3.0X4321>>4<<4=? 0x4320
应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。
右移相当于除法,左移相当于乘法
延伸:
逻辑移位(不管是左移位还是右移位) 都是空缺处补0
例如: mov ax , 1100_0111_0110_1000B
mov cl , 3
shl ax , cl ; 结果 ax = 0011_1011_0100_0000
mov ax , 1100_0111_0110_1000B
mov cl , 3
shr ax , cl ; 结果 ax = 0001_1000_1110_1101
算术移位要保证符号位的不改变(逻辑左移位补0, 逻辑右移位看符号位)
例如: mov ax , 1100_0111_0110_1000B
mov cl , 3
sal ax , cl ; 结果 ax = 0011_1011_0100_0000
mov ax , 1100_0111_0110_1000B
mov cl , 3
sar ax , cl ; 结果 ax = 1111_1000_1110_1101
mov ax , 0100_0111_0110_1000B
mov cl , 3
sar ax , cl ; 结果 ax = 0000_1000_1110_1101
可以总结如下:
算术左移同逻辑左移
算术右移移入的位用符号位填
逻辑右移移入的位用0填
4.#define SQR(x) (x*x)
inline int sqr(x)
{
return x*x;
}
什么情况下结果不同
解:++i
这个知识点考察的是#define只是字符串替换作用,以及++i在表达式中使用的是其改变后的值,i++在表达式中使用的是其改变前的值
5.
union DATE
{
char a;
int i[5];
double b;
};
struct date
{
int j;
DATE d;
float f;
};
DATE max;
void main()
{
cout << sizeof( struct date ) << "/t" << sizeof(max) << endl;
}
用vc运行
为什么输出:40 24
union DATE
{
char a;
int i[5];
double b;
};
①联合就是一个结构,②它的所有成员相对于基地址的偏移量都为0,③此结构空间要大到足够容纳最“宽”的成员,④并且,其对齐方式要适合于联合中所有类型的成员。
该结构要放得下int i[5]必须要至少占4×5=20个字节。如果没有double的话20个字节够用了,此时按4字节对齐。但是加入了double就必须考虑double的对齐方式,double是按照8字节对齐的,所以必须添加4个字节使其满足8×3=24,也就是必须也是8的倍数,这样一来就出来了24这个数字。综上所述,最终联合体的最小的size也要是所包含的所有类型的基本长度的最小公倍数才行。(这里的字节数均指winnt下的值,平台、编译器不同值也有可能不同。)
另外对于:
union DATE
{
char a;
int i[5];
double b;
};
struct date
{
int j;
DATE d;
float f;
};
结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
而编译器默认为:
#pragma pack(8) //可以更改在:vc6中打开工程属性页,c/c++页,选择Code Generation分类,
在 Struct member alignment可以选择。
所以DATE的对齐方式就是以8的倍数开始的.
所以DATE的内存分存就如下:
jjjj****
dddddddd
dddddddd
dddddddd
bbbbbbbb
sizeof(date)=8+24+8=40