一道程序的分析
来源:互联网 发布:linux 查看arp 编辑:程序博客网 时间:2024/06/11 16:56
以下是程序的内容:
#include <stdio.h> int main() { int a[5]={1,2,3,4,5}; int *ptr1=(int *)(&a+1); int *ptr2=(int *)((int)a+1); printf("0x%x,0x%x\n",ptr1[-1],*ptr2); return 0; }
在C-Free下运行的结果是:
Ptr1[-1]的值是0x5;
*ptr2的值是0x2000000。
1.大端模式和小端模式
大端模式:字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
小端模式:字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
假设定义一个整形变量i,将它初始化为1,那么它采用大端模式存储的情况下,它在内存中的布局如图1.1所示。而它如果采用小端模式存储的情况,在内存中的布局如图1.2所示。
在x86模式下,CPU主要是工作在小端模式下的。而ARM则在大端模式和小端模式下都可工作。
可以采用下面一段代码来验证当前系统采用何种存储模式:
#include "stdio.h" int checkSystem(); int main() { printf("%d\n",checkSystem()); } int checkSystem() { union check { int i; char ch; }c; c.i=1; return (c.ch==1); }
如果printf输出的值为1,则说明当前系统采用的存储模式为小端模式;如果输出的值为0,则说明当前系统采用的存储模式为0。
这段判断程序的依据是:
- 联合体union分配了一段内存,多种不同类型的变量都可以存放到这一段内存中,也就是说,它们共同使用这一段内存。由于在union中,所有的数据成员都共同使用一段内存,所以同一时间只能存储一个数据成员,而且所有的数据成员都拥有同一个起始地址。在上面的程序中,数据成员i和ch拥有同一个起始地址。大家可以做一个试验,首先令c.i=1,然后令c.ch=2,然后分别打印这两个数据成员的值。结果是这两个数据成员的值都为2,这说明联合体union采用了覆盖的方法保证同一时间只能存储一个数据成员。
- 联合体union的存放顺序是所有成员都从低地址开始存放的,所以,利用这个特性,我们可以很方便地判断当前系统的存储模式。假如采用小端模式存储,当然低地址的内容就为1;采用大端模式存储,那低地址的内容就为0,而1就存储到高位地址去了。
2.数组首地址和数组首元素的首地址
这里重申一下&a和a区别,为后面的分析准备一下。&a是指整个数组的首地址,而a则是数组首元素的首地址,即a[0]的地址。其实&a和a的值是一样的,但是两者所代表的意义是不同的,这是需要特别注意的。
3.分析ptr1和ptr2
首先,我们来看看数组的内存地址,如图3.1。由于数组a是整型的,所以每一个数组元素占用4个字节的空间。这里a[0]~a[4]五个元素都只占用了1个字节的空间,其余的三个字节都没有使用,填充为0,如图3.1中红色的方框中所示。
接着,我们再看看ptr1所代表的意义。首先,ptr1是一个指针,指针的本质是地址。将(&a+1)先强制转型为与ptr1相同的类型,即int*类型,然后将它赋给变量ptr1。前面我们说过,&a代表整个数组的起始地址,那么(&a+1)所代表的就是这整个数组的下一个整型数据。因而,ptr1指向的就是现在这个数组结束以后的整型数据的空间。ptr1所指向的地址就是0x22ff34,也就是图3.1中蓝色方框中第一个字节的这个部分。ptr1[-1]会被解析成*(ptr1-1),那么ptr1-1就是后退4个字节,所指向的是0x22ff30这个地址。因此,打印出ptr1[-1]的值就是5。
然后,我们再来分析ptr2所代表的意义。如前面所说a所代表的意义是元素a[0]的地址,那么就是0x22ff20这个地址。将a强制转型为int类型之后再加1,所代表的意义是a[0]元素的第二个字节的地址,即0x22ff21。将(a+1)再强制转型为与ptr2相同类型的int*以后赋值给ptr2,这样以后,ptr2即指向0x22ff21这个地址。那么,*ptr2就是指以0x22ff21开始的4个字节的地址中的内容,即图3.1中绿色部分所指的内容。由于x86 32位系统是以小端模式存储的,低位存储低位字节,高位存储高位字节,所以我们打印出来的结果就是0x2000000。
- 一道程序的分析
- 一道程序的分析
- “一道无聊的程序题”
- 一道面试题的分析
- 一道面试题的分析
- 一道面试题的分析
- 一道数学问题的程序解答
- 一道简单的C程序--考考你
- 关于一道招聘题的分析
- 一道面试题的分析(续)
- 对一道题的算法分析
- 一道有趣的数学题分析步骤
- 一道算法面试题的分析
- 一道简单题目的数据结构算法分析
- 关于一道java面试题的分析
- 一道经典的java面试题分析
- 一道关于加载顺序的题目分析
- 昨晚阿里巴巴的一道面试题分析
- Instruments检查视图卡顿和优化
- 20160416
- [LeetCode]70. Climbing Stairs
- ubuntu下使用VNC连接树莓派raspberry
- 【ATF】钱正平:大规模实时计算及其在阿里的应用与创新
- 一道程序的分析
- ubuntu14.04配opencv2.4.11
- EasyUI体验-分页多选,选项保留,以及历史记录相结合的保留
- String,StringBuffer,StringBuilder之间的区别
- 方便学习的一些经典网站
- SLAM学习
- 数据平台的简单使用
- Light OJ 1342 - Aladdin and the Magical Sticks (概率DP)
- VS2013中 scanf()函数返回值