2019独角兽企业重金招聘Python工程师标准>>>
如无特殊,均为`gcc test.c -o test`的类似方式编译源文件。
在这里主要讨论`int*`,`int**`,`char*`,`char**`等这些比较基本的指针类型,主要以int类型为示例。在64bit环境中地址用8B表示,int类型是4B。
关于直接寻址、间接寻址
参见相关汇编语言、计算机组成原理的书籍。
关于int *
`int *p`定以了一个整型指针变量p,p本身存放的是一个int变量的地址,即在32位机器上int变量为2Bytes,p实际为4Bytes,因为地址要用32bits表示。
若有以下代码:
#include <stdio.h>
int main()
{int *p;printf("%p\n",p);printf("%d\n",*p);return 1;
}
编译时会提示:`warning: ‘p’ is used uninitialized in this function [-Wuninitialized] `。 运行时显示:
(nil)
Segmentation fault (core dumped)
这是因为声明p时候,分配的8个字节原先的内容并没有被抹去,故p指向的内容不定,甚至指向内核,这是OS不允许的。 下面这段代码就可以正常运行:
#include <stdio.h>
int main()
{int i; //默认初始化为0int *p=&i;printf("%p\n",&i); //打印int变量i的地址printf("%p\n",&p); //打印int指针变量p的地址printf("%p\n",p); //打印p本身的内容printf("%d\n",*p); //打印p本地代表的内存地址指向的值,即i的值。return 1;
}
运行结果为:(注意内存对齐的概念) 0x7fffcbaecf5c
0x7fffcbaecf50
0x7fffcbaecf5c
0
内存组织如下:从内存0x7fffcbaecf5c处开始4个Byte存放int变量i,从0x7fffcbaecf50开始的8个Byte开始int指针变量p的值,而这个值对应的内存单元在使用*p取值时只会取4个Byte。调用i时候类似直接寻址,调用`*p`时候类似间接寻址。因为p是`int`型指针。注意`int i;int*p=&i;`与`int i;int *p;p=&i;`是等价的,从这个角度来讲,可以把`int *`单独看作一种类型。虽然`int i;(int *)p=&i;`是错误的,但是比较容易理解(至少对我而言),例如在经典的交换数值问题上: #include <stdio.h>
void swap(int *p1,int *p2);
int main()
{int i=0,j=1;swap(&i,&j);printf("i=%d,j=%d\n",i,j);return 1;
}
void swap(int *p1,int *p2)
{int temp;temp=*p2;*p2=*p1;*p1=temp;
}
对于swap函数的参数`int *p1`,`int *p2`,只看p1、p2,两者是int型指针,本身代表地址。 所以调用的时候需要把地址填入里面,也就是&i、&j,注意i和j必须是int类型。 在上面的swap代码修改如下:
#include <stdio.h>
void swap(int *p1,int *p2);
int main()
{int i=0,j=1;printf("i addr:%p ,value:%d ; j addr :%p ,value:%d \n",&i,i,&j,j);swap(&i,&j);printf("i addr:%p ,value:%d ; j addr :%p ,value:%d \n",&i,i,&j,j);return 1;
}
void swap(int *p1,int *p2)
{printf("p1 value:%p , p2 value:%p ; *p1 value :%d , *p2 value:%d \n",p1,p2,*p1,*p2);int temp;temp=*p2;*p2=*p1;*p1=temp; printf("p1 value:%p , p2 value:%p ; *p1 value :%d , *p2 value:%d \n",p1,p2,*p1,*p2);
}
输出可能如下:
i addr:0x7fff6ce4b608 ,value:0 ; j addr :0x7fff6ce4b60c ,value:1
p1 value:0x7fff6ce4b608 , p2 value:0x7fff6ce4b60c ; *p1 value :0 , *p2 value:1
p1 value:0x7fff6ce4b608 , p2 value:0x7fff6ce4b60c ; *p1 value :1 , *p2 value:0
i addr:0x7fff6ce4b608 ,value:1 ; j addr :0x7fff6ce4b60c ,value:0
可以看出,在main()中调用swap()时候传递的是地址。如