题目:
#include<stdio.h>
int main(){
int a=301; // 1_0010_1101B
int x=1;
x>>8?printf("big\n"):printf("small\n"); //检测大小端
char *p=(char *)&a;
printf("%d,%d",*p,*++p);
return 0;
}
/*
首先面对两个问题:1, int 型被强转为char型 ,那 a 的值为? 2 , * 和++ 优先级问题
printf("%d,%d",*p,*++p); //(pirntf 计算参数%d顺序问题,对 ++ 运算有影响的。)
*/
//win10 DEV编译器 答案:small 1,1
解释:
第一个问题:
注意: 一个字节 = 8 bit , 十进制 简称 D , 二进制 简称 B。
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。 ----百度百科
运行结果看见是小端模式,int a = 301 在内存储存格式为 图1 . 301(D) = 0001 0010 1101(B)
内存地址 | 内容 二进制数据 |
FFFC1 低地址 | 0010 1101 低字节 |
FFFC2 | 0000 0001 |
FFFC3 | 0000 0000 |
FFFC4 高地址 | 0000 0000 高字节 |
图 1 小端模式储存 int a=301
char 占一个地址 , int 占四个地址 。int 型强转为char 型 时,char 就是图中 FFFC1地址所在的内容数据 0010 1101。
所以强转之后的a 的值是地址为 FFFC1所在的值:0010 1101 (B) = 45 (D)
第二个问题:
++ 和 * 是同一个优先级 ,那就看运算顺序,是自右向左的,所以 *++p 是先自加(++),在取值(*) 的。*++p 的地址就是FFFC1加一的地址FFFC2所在内容 0000 0001(B) =1 (D)
------------------------------------------------------------------------------------
好了,自己模拟计算答案了,printf("%d,%d",*p,*++p); // 输出 45 ,1 ^ -- ^ ,哎,和答案不一样呢,
坑好多,见下文解释,printf()运算参数是自右向左的,真搞不明白,这样就是先计算 *++p ,在计算 *p, 答案就是 1 ,1 了。
心累。
**************************************************************
无论在什么系统printf的执行顺序都是从右至左,只不过编译器不同,程序内存分配方式不同,i++对i加1的时机也不同,所以结果不同。 printf("%d,%d,%d\n",i++,++i,i); 出现4,5,5的结果比较好理解:i和++i都共享一个内存,也就是为i分配的内存;而执行i++会为表达式单独分配内存,把当时i的值存储进去,然后i加1;所以执行printf语句时,i初始值为3,执行++i后,i变为4,执行i++先把为表达式分配内存,表达式的值为4,然后i加1变为5;最后输出时,i++这个表达式的值为4,而++i和i都用此时为i分配的内存的值,也就是5。之所以这样分配可能是编译器优化内存分配方式,节省内存吧。总结起来就是,编译器会为i++表达式实时单独分配内存,而i和++i由始至终都共享i的内存,最后输出时,i++输出当初执行i++时的表达式的值,而i和++i输出最后i的内存中的值。 出现4,4,3的结果比较不让人理解,我看也就是vc6.0这么诡异:无论是i,i++还是++i,编译器都会为当时的表达式单独分配内存,从右向左执行时,i表达式的值存为3,i仍为3,++i表达式的值为4,i变为4,i++表达式的值为4,i仍为4,为什么仍为4,因为要等到printf这条语句执行完以后,i才会+1变为5。假如在这个i++左边再添加一个i,用来输出,那么它仍为4,也就是说printf("%d,%d,%d,%d",i,i++,++i,i)的结果为4,4,4,3。不过下一条printf语句输出i的结果就是5了。总结起来是这样,在vc6.0里i,i++和++i都会实时为各自表达式单独分配内存,++i对i的影响是实时的,但是i++对i的内存的值的影响是等到本条printf语句执行完才起作用。 我们平常说i++是对i先使用后加一,也就是先把i作为表达式的值,然后把i加1赋给i,通常认为这个“后”是在i++这个式子之后,没想到vc6.0中,这个“后”竟然要后到整条printf语句执行完以后。