现在的位置: 首页 > 综合 > 正文

c语言指针深解

2013年05月04日 ⁄ 综合 ⁄ 共 5452字 ⁄ 字号 评论关闭

关于C语言的指针,相信有很多人都已经明白了它是什么意思,但是也有很多人处在迷茫之中,我们一起来看看吧

 

 

指针就是其值为内存地址的变量---------直观的理解,可以参考

 

 

变量是直接引用变量的值,而指针是间接(通过值的地址)来引用变量的值------只管理解,可以参考

 

 

指针可以被初始化为0,null,或一个地址值

 

 

也许通过实验能更加深理解:

 

 

int main()
{
int a;
int *p;

//现在我们初始化a

a=47;
p=a;

printf("%d/n",p);
}

 

 

vs 2008:

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(11) : warning C4047: “=”: “int *”与“int”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,1 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

输出47

 

 

---------------------------------------------------------------------------------------------------------------

 

 

其实指针变量也是变量,你可以对它赋值,这没有什么好奇怪的!

 

 

#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=47;
p=a;
c=&a;

printf("%d/n",p);
printf("%p/n",c);

}

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
输出:

 

47
0012FF60
请按任意键继续. . .

 

 

--------------------------------------------------------------------------------------------------------------------------------

 

其中%p是格式化输出标记,他说了:“用系统实现时所定义的方式(这个系统是以哪种方式来显示指针,这里很显然是十六进制的)显示一个指针的值”

 

呵呵,可我们显示的是c,仅仅是一个普通的int类型,它的值是一个地址!!他以16进制的方式显示了这个地址(a的地址)的值。

 

 

#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=47;
p=a;
c=&a;

printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
}

 

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

输出:

47

0012FF60

0000002F

 

 

呵呵,看清楚了吧,%p不是跟指针绑定的,他只是说:“以这个系统显示指针的方式来显示这个数!”,他有什么别的权利!

 

 

#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=47;
p=a;
c=&a;

printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
}

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

输出:

47

0012FF60

0000002F

0012FF48

 

 

很简单,最后一行输出的是c的地址的值(我们知道了p在这个系统中就是以十六进制来显示的,所以我们用p来格式化输出),c本身的值也是一个地址(是a的地址),但是你应该知道什么是什么!

 

 

到了这里你还没有看到指针到底有什么特别之处,你所看到的指针变量的功能和普通的变量似乎没有什么区别,正象第一行输出那样,他被赋予了一个整数值然后就被输出了!!

我们需要时刻记住,一个指针变量是用来存储地址的,但是整数值也可以表示地址,所以我们将一个整数值赋予一个指针变量也没有什么不妥的地方,这就同将一个地址的整数值赋予他是一样的。也许你有兴趣看一下地址为47的这个内存单元中存储的内容,我们试试吧!

 

#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=0x000019b0;
p=a;
c=&a;

printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
}

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

这里可以通过编译,但是却不能运行,这是为什么呢(而我们所做的改动仅仅是最后一行的输出语句,也就是说问题出在输出语句上)??能通过编译,说明了编译器并不认为我们的改动有什么错误!!!但是为什么不能运行呢??

 

 

、#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=47;
p=0x0012FF60;
c=&a;

printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
}

 

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(14) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

正常编译,正常运行

 

1245024

0012FF60

0000002F

47

 

我们将a的地址赋予 p,这个时候我们再*p就可以正确得到了输出 值47!!

 

上一个例子我们不能执行呢?我们不知道内存的47单元是否有可用的值!!!!有吗?我们不知道!!!但是我们想知道,到底怎么办!!!

 

#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=47;
p=0x0012FF60;
*p=99;
c=&a;

printf("%d/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
printf("%d/n",a);
}

 

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(15) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

输出:

1245024

0012FF60

0000063

99

99

 

可见,我们通过指针改变了变量a的地址单元的值,哈哈,你也许认为我们能通过这样的方式来改变其他地址的值!!这样的想法对吗????

 

 

#include<stdio.h>

int main()
{
int a;
int *p;

int c;

//现在我们初始化a

a=47;
p=0x0012FF58;
*p=99;
c=&a;

printf("%x/n",p);
printf("%p/n",c);
printf("%p/n",a);
printf("%p/n",&c);
printf("%d/n",*p);
printf("%d/n",a);
}

 

------ 已启动生成: 项目: CFile, 配置: Debug Win32 ------
正在编译...
hello.c
e:/code/net/c语言/hello.c(13) : warning C4047: “=”: “int *”与“int”的间接级别不同
e:/code/net/c语言/hello.c(15) : warning C4047: “=”: “int”与“int *”的间接级别不同
正在链接...
正在嵌入清单...
生成日志保存在“file://e:/Code/NET/C语言/CFile/CFile/Debug/BuildLog.htm”
CFile - 0 个错误,2 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

 

正常编译可以运行:

 

12ff58

0012FF60

0000002F

0012FF48

99

47

 

惊呼吧,似乎发现了新大陆,可是我们把0x0012FF58改成0x0012FF59你会看到不能运行,你会发现系统提示你a的地盘被入侵了!!!!呵呵!!!改成其他值似乎也不能解决不能运行的现象。

 

栈是个好东西,你不能破坏他的规矩,你要按照规矩来,你不能做超出规矩的动作!!

 

你必须遵循内存中栈的规则,否则你将破坏内存的分配机制,进而做出不安全的操作!!这是一中保护措施!!这里间隔2的地址是可以赋值的!!但是要记住一定得不侵犯别人的东西!!

 

所以呢,你如果要通过这样的方式来改变内存中的值,你必须对内存的状况透彻地了解,可是似乎我们没有这么大的能力吧!!

 

所以通过变量来实现这样的动作更理智和现实!!

 

所以呢,你可以看到指针的作用:你就是用她来保存一个变量的地址!!然后呢,你可以直接来得到那个变量的地址!!然后呢,你可以通过*P的形式,来访问或者修改这个变量的值!!而普通的变量,你就不能在之前面加上*来访问这个变量的值所代表的内存单元的值,这个是指针变量的专利产品!!

 

 

 

 

 

 

抱歉!评论已关闭.