深入浅出 C语言指针 一
2005-06-17 16:29
190 查看
指针是什么? 是地址。这个大家都知道。但是理解得未必深刻。我们以一条条活生生的代码来分析。
int *pointer;
声明一个指针。 pointer是一个指向Int型的指针的变量。
而变量里面的值是一个内存地址(在大部分操作系统中不是物理地址,是经过地址映射后的虚拟地址)。
而这个pointer只在程序文件(.c,.cpp)里存在,当编译成可执行文件后,它被替换成一个难看的符号,比如LLC012什么的。这点与java相反,所以C程序是没有办法反编译的。
当运行一个C程序时,操作系统分配给LLC012一块32位大小内存地址,以后你改变指针的值时,改变的就是这块内存地址的值了。
int 是指针的类型,刚才说过,指针变量占用的内存空间永远是32位,相当于一个int的大小。但是,指针是有类型的,它不是用来给指针变量本身分配内存,它是用来做什么的呢? 它是 用来寻址 的。看下面的代码。
(int*)pointer = malloc(sizeof(int) * 5);
printf("%d",*(pointer + 1));
这段代码中先申请5个int大小的内存空间,把这段内存空间的首地址付给pointer。然后打印出第2个int元素的值。
如果这里的pointer是char类型的,那么pointer+1指向的不是第2个Int,而是第一个int的中间部分。也就是说对于不同变量类型的指针来说,+1跨过的内存单元数是不同的。指针的类新也可以是自定义的结构的类型。
与java不同,C语言的函数是不允许以引用的方式传值的,也就是说对于所有的C函数,传入的参数都是一个复制的值。
比如这样一个交换数值的函数
void switch(int a ,int b)
{
int c =a;
a = b;
b = c;
}
这个函数调用后实际上并没有交换两个参数的值,因为是传值的,而非传地址(引用)的。
那么我们如何实现累类似引用传值的功能呢? 答案是,用指针。
void switch(int* a ,int* b)
{
int c =*a;
*a = *b;
a4dc
*b = c;
}
从本质上说指针也是被复制后传到函数体内的。
我们以上面这个函数为例分析一下
函数一 : 当调用 switch(intA,intB)时
假设 :
intA 地址 0X0000000A 值 1
intB 地址 0X0000000B 值 2
经过复制之后实际上传入函数的是另外两个。
a 地址 0X000000AA 值 1
b 地址 0X000000BB 值 2
当函数执行后,intA,intB的值没变,他们从头到尾都没进入函数,进入的是他们的副本。变的是a , b的值(如下),但是函数执行结束后a , b都已经被丢弃了。没有达到预期目的。
a 地址 0X000000AA 值 2
b 地址 0X000000BB 值 1
函数二 : 当调用 switch(*intA,*intB)时
假设 :
intA 地址 0X0000000A 值 0X00000A0A
intB 地址 0X0000000B 值 0X00000B0B
地址 0X00000A0A 值 1
地址 0X00000B0B 值 2
当函数执行时,先复制参数,结果如下
a 地址 0X000000AA 值 0X00000A0A
b 地址 0X000000BB 值 0X00000B0B
而地址0X00000A0A 和 0X00000B0A 的值没有变化
传入函数后用的都是指针变量的值,也就是说改变的是0X00000A0A 和0X00000B0B的值,而指针intA和intB的值没有变化,始终指向0X00000A0A 和0X00000B0B 所以最终达到交换数值的预期效果。
int *pointer;
声明一个指针。 pointer是一个指向Int型的指针的变量。
而变量里面的值是一个内存地址(在大部分操作系统中不是物理地址,是经过地址映射后的虚拟地址)。
而这个pointer只在程序文件(.c,.cpp)里存在,当编译成可执行文件后,它被替换成一个难看的符号,比如LLC012什么的。这点与java相反,所以C程序是没有办法反编译的。
当运行一个C程序时,操作系统分配给LLC012一块32位大小内存地址,以后你改变指针的值时,改变的就是这块内存地址的值了。
int 是指针的类型,刚才说过,指针变量占用的内存空间永远是32位,相当于一个int的大小。但是,指针是有类型的,它不是用来给指针变量本身分配内存,它是用来做什么的呢? 它是 用来寻址 的。看下面的代码。
(int*)pointer = malloc(sizeof(int) * 5);
printf("%d",*(pointer + 1));
这段代码中先申请5个int大小的内存空间,把这段内存空间的首地址付给pointer。然后打印出第2个int元素的值。
如果这里的pointer是char类型的,那么pointer+1指向的不是第2个Int,而是第一个int的中间部分。也就是说对于不同变量类型的指针来说,+1跨过的内存单元数是不同的。指针的类新也可以是自定义的结构的类型。
与java不同,C语言的函数是不允许以引用的方式传值的,也就是说对于所有的C函数,传入的参数都是一个复制的值。
比如这样一个交换数值的函数
void switch(int a ,int b)
{
int c =a;
a = b;
b = c;
}
这个函数调用后实际上并没有交换两个参数的值,因为是传值的,而非传地址(引用)的。
那么我们如何实现累类似引用传值的功能呢? 答案是,用指针。
void switch(int* a ,int* b)
{
int c =*a;
*a = *b;
a4dc
*b = c;
}
从本质上说指针也是被复制后传到函数体内的。
我们以上面这个函数为例分析一下
函数一 : 当调用 switch(intA,intB)时
假设 :
intA 地址 0X0000000A 值 1
intB 地址 0X0000000B 值 2
经过复制之后实际上传入函数的是另外两个。
a 地址 0X000000AA 值 1
b 地址 0X000000BB 值 2
当函数执行后,intA,intB的值没变,他们从头到尾都没进入函数,进入的是他们的副本。变的是a , b的值(如下),但是函数执行结束后a , b都已经被丢弃了。没有达到预期目的。
a 地址 0X000000AA 值 2
b 地址 0X000000BB 值 1
函数二 : 当调用 switch(*intA,*intB)时
假设 :
intA 地址 0X0000000A 值 0X00000A0A
intB 地址 0X0000000B 值 0X00000B0B
地址 0X00000A0A 值 1
地址 0X00000B0B 值 2
当函数执行时,先复制参数,结果如下
a 地址 0X000000AA 值 0X00000A0A
b 地址 0X000000BB 值 0X00000B0B
而地址0X00000A0A 和 0X00000B0A 的值没有变化
传入函数后用的都是指针变量的值,也就是说改变的是0X00000A0A 和0X00000B0B的值,而指针intA和intB的值没有变化,始终指向0X00000A0A 和0X00000B0B 所以最终达到交换数值的预期效果。
相关文章推荐
- 用C语言指针作为函数返回值
- C语言 二级指针内存模型混合实战
- C语言复杂指针声明应如何阅读
- C语言 free 指针 变量内存分配
- C语言中 数组与指针的不同 。 char[] 与 char*
- C语言速成手册(四):指针、动态内存分配、标准输入
- c语言的值传递、指针传递、引用传递的区别
- C语言回顾(六、基类型,数组指针,字符串指针,函数指针,文字常量区)——iOS开发基础
- C语言 多维数组和多维指针
- 【C语言】13-指针和字符串
- C语言回顾(七、多重指针,argc,argv,动态内存分配,void指针,const)——iOS开发基础
- 【c语言问题系列教程之四】指针
- C语言:指向指针的指针
- 【C语言】14-返回指针的函数与指向函数的指针
- [C语言]当数组结合指针,会迸发出什么火花?我相信这火花会让你头晕目眩!!
- 【学习ios之路:C语言】②高级指针应用
- 【C语言】 浅谈指针
- C语言常量与指针
- 深入理解C语言指针的奥秘
- C语言里函数指针的两种常见用途(回调函数与转移表)