您的位置:首页 > 其它

【C】 指针与地址

2014-12-11 19:31 99 查看

初探指针

什么是指针?为什么要用指针?

指针是一种保存变量地址的变量,存放在一组连续的存储单元中(通常是2或4个,后者居多)。因为C语言本身的feature就很少,加上指针又非常的高效,指针已然成了C最大的特点。与指针相关的操作符有两个,分别为 * (解引用)和 & (取地址),解引用这个词比较令人费解,比方存在指针p, p = &c ,p中便保存了 c 的地址,通过 * p 来得到地址中的内容,所以我更喜欢将它看做“解指针”,解开指针中的内容嘛

怎么用?

还是用上面这么例子

int a = 5;
int *p = &a;
printf("%d",*p);
printf("%p",p)

第一个printf输出了指针p所指的对象a,即5 ,第二个printf输出了p保存的内容,即a的地址。注意,取地址符号&只能作用于内存中的对象,即变量与数组元素,不能作用于表达式,常量或register变量。
再举一栗

int a = 5;
int *p = &a;
printf("%d",*p);
int *q = p;
*q = 10;
printf(''%d",*p);

第一个printf输出5没问题,接着又把p赋给了另一个指针变量q,此时,q中也保存了a的地址,对 *q的修改就是对 a 的修改,再输出 *p 的时候结果已经变成10了
那么既然指针保存的是地址,那么指针能不能保证另一个指针的地址呢?显然可以嘛,这就是所谓的

二级指针

int a = 5;
int *p = &a;
int **q = &p;不妨分别输出 p, *p ,q ,*q ,**q看一看,其中,p 是 a 的地址,*p 是5,q 是p的地址,*q是p保存的内容,即a的地址,**p是5,如果觉得抽象的话可以画张图来看看,典型的链表的结构

指针和地址

由上面已看出,指针的操作很多都是和地址相关的,在进一步了解两者的联系之前,不妨先来看看地址。

内存把若干的存储单元(以字节表示最小单元)有序的组织起来,并在逻辑层面上给我们提供了一个地址,比如0x11FF88(通常以16进制表示),而单个字节又太小不足以表示出所有的数据类型,就把4个字节合并为了一个字(比如32位的系统),来存放数据。那么,知道了地址就可以把里面的数据去出来了吗?非也。光知道地址还不够的,还得知道里面的数据存储的方式(大小端)和数据的类型,否则即使取出来也多是没用的乱码

如何判别大小端

short int x;
char x0,x1;
x=0x1122; //11是高字节,22是低字节
x0=((char *)&x)[0]; //低地址单元
x1=((char *)&x)[1]; //高地址单元
printf("x0=0x%x,x1=0x%x\n",x0,x1);//小端模式,高字节放在高地址中 大端模式,高字节放在低地址中知道了机器存储数据是按大端还是小端的,我们就知道按什么顺序去一个字节一个字节的读里面的数据了,之所以平时用不到是因为机器已经帮我们做好了。
举个例子,我们可以一个字节一个字节读读一个4字节的int,并输出其二进制的表示

void print_2(int val2)
{
unsigned char *p = (unsigned char*)&val2 + 3; //本机器是以小端的方式存储数据的,高字节放在高地址中
int k;
for( k = 0; k <= 3; k++)
{
int val2 = *(p-k);
int i;
for ( i = 7; i >= 0; i--)
{
if(val2 & (1 << i))
printf("1");
else
printf("0");
}
printf(" ");
}
}

比如62,输出 00000000 00000000 00000000 00111110

由地址取出数据

假设我现在已经知道了一个地址是0x11FF00,以此开头的地址存放着一个Int 型的数,62,机器是按小端的方式存储的,即

0x11FF03          00000000

0x11FF02          00000000

0x11FF01          00000000

0x11FF00          00111110

怎么取呢?首先,要将对应的地址转换为相应类型的指针,这样编译器才知道你要去多长

比如,要把这个int型的62取出来,先将地址强制转型为 int*,  (int *)(0x11FF00)  ,在通过 * 将其中的内容取出来。(PS:在实际中别这么写,地址不能随便访问的,你可以写成 &a 来取变量的地址)

若只取 0x11FF00这一个字节呢?

char *j = (char*)(0x11FF00);
printf("%d\n",*j );
printf("%c\n",*j);
注意,在只取了一个字节后,分别按照了不同方式打印,%d打印出的是62,而%c打印出的是 > ,对照ASCII码,62对应的正是 >,可见的确只打印出了一个字节。

好了,先记下这么多,指针太博大精深,日后再慢慢探究

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: