| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2787 人关注过本帖
标题:指针与地址
只看楼主 加入收藏
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
结帖率:96.55%
收藏
 问题点数:0 回复次数:12 
指针与地址
有一些书和视频中会提到这样一件事情:指针就是地址。这中说法貌似很盛行,尤其是在不会熟练使用指针,甚至搞不清楚指针的本质的人群被奉为真理。

笔者的观点是:虽然在代码过程中可以认为指针就是地址,但如果细究,它们是有区别的。

为了论证上述观点,我们必须从头开始,首先讲述类型与变量。

在C语言中,我们若想使用某个变量,就必须提前声明。想要使用short类型的变量,就需要先声明;想要使用int类型的变量,也要先声明。其实我 们声明变量其实是告诉编译器,我们需要一块内存空间,具体空间大小由变量类型决定。short类型的变量需要2字节,int类型的变量需要4字节。

类型是一个抽象概念,它描述了其变量所占用的内存空间大小、如何解析其值在内存中的表示以及在其变量上可以发生的操作。
int类型的变量可以进行四则运算,但指针类型变量却只能进行加运算,而且指针类型变量的加运算不是数学意义上的加运算。
变量是类型的具体事物,它的属性包括所属类型、地址以及值。变量所占的内存空间大小和可发生的操作都是有其所属类型决定。

某些书籍教程中提到,变量的值就是其内存单元中保存的数据。这是一种错误的观点。内存单元中保存的数据仅仅变量值的一种表达,而非变量值本身。举个 例子来说,int类型的变量a,我们给其赋值为-1,但内存单元中保存的却是FFFFFFFF(十进制值为4294967295);另有一个 unsigned int类型的变量b,我们给其赋值为0xFFFFFFFF。两个变量在内存中存储的数据完全一样,但两者所表达的值却完全不一样。看似无法区分-1和 4294967295,但编译器总是不会发生错误。因为编译器知道变量的类型不同,依据类型完全可以区分出来。

有两个类型的变量:int c = 0x1234;,short d = 0x1234;。两个变量虽然其值在内存中的表示完全一样,但其类型不同,访问的内存空间大小也不一样。变量c访问了4个字节,而变量d只访问了2个字节。
我们说整型变量c和d的值是一样的,其实并非说内存空间中存储的位组合完全一样。值是变量的一种属性,但内存空间中存储的位组合只是变量的值的一种表达,区分两者是非常重要的。

下面我们看看指针是怎样的。指针其实不是C语言独有的,汇编语言其实也是有指针,只是被称为间接寻址之类的。我们对变量的引用本质上是对变量的地址 的引用。我们知道某个变量的地址是无法访问这个变量,因为CPU不知道这个变量所占的内存空间是1个字节还是2个字节还是4个自己,甚至更多。只有知道变 量的地址和它所占用内存空间的大小才能正确引用变量,而指针正是表述地址和空间大小的事物。CPU访问变量依据的正是指针,但编译之后的程序中无法直接表 达指针。对于基本类型变量的访问,CPU是通过一次访问1、2或4字节内存空间来实现,但对于复杂的数据类型并非如此。可以说,对于基本类型,指针存在于 编译后的二进制代码中;但对于复杂类型,指针只存在于编译器中,编译器把对复杂类型变量的访问拆分成对简单类型变量的访问。

我们说0x1234的值是就是0x1234,这中说法确实也没问题,因为整数是个标量。但我们能否直接说指针的值是0x1234?答案是错误的,因为指针并非一个标量。我们只能这样正确表达一个指针:地址是0x1234并且大小为4个字节的指针。是的,这才是指针的值!
搞清楚了指针,我们再来看看指针类型。首先必须澄清的一种观点是,指针类型不是一种类型,而是间接引用其他类型(包括指针类型)的一类类型。我们要 提一种指针类型,必须说清楚它所引用的是哪种类型。比如:指向int类型的指针类型,或简单地说是Int指针类型。同样的,我们只能说指向int类型的指 针变量,或简单地说int指针变量,但不能简单地说指针变量。

指针变量也是有值的。int e = 5; int * p = &c;,其中变量e的地址是 0x9000000, 那p的值是什么呢?有人说p的值就是变量e的地址,也就是0x9000000。这种说法是错误的。变量p在内存空间中的存储位的组合确实是 0x9000000,但指针变量的值是指针,而非指针在内存空间中的表示。正确的说法是:地址为0x9000000,占用4个字节的指针。
我们看看下面的代码片段:

int e;
int * p;
e = 5;
p = &e;

那么p = &e;这一句到底是怎么回事呢?或者说,指针变量的值确实如我前面所说是指针呢?&我们称为取值符号,如果&符号得到的是地址,那么下面的代码是正确的:

unsigned short * p;
unsigned short a = 0x3412;
unsigned int b = 0x7856;
p = &a;
p1 = &b;

但实际情况是,对于p1 = &b;这一句,编译器无法通过,而且是个错误。看来&符号得到的并不是地址,因为如果是地址,那么就说明是同一种事物,可以直接赋值。

我们再看看下面的代码:

unsigned short * p;
unsigned short a = 0x3412;
unsigned int b = 0x7856;
p = &a;
p = (unsigned short *)&b;

这两个代码段的区别是在&b前面多了(unsigned short *)。实际上&符号取到的是指针而非地址。&b取到的是指针的值是:地址为变量b的地址,占用空间是4个字节。但p所指向的变量所占用的 空间是2个字节,所以需要进行强转。注意,这里转换的是指针而非变量。

另外,我们再简单谈谈*符号:*符号取得的是指针变量指向的变量,而而非指针变量指向的变量的值。在表达式中对变量的引用其实是取变量的值,这一步操作是隐形的。

有了上述,我们看下面的代码就比较容易了:

unsigned int a = 0x12345678;
unsigned int * p1 = &a;
unsigned char * p2 = (unsigned char *)&a;
printf("a  : %x\n", *p1);
printf("a的第一个字节 : %x\n", *p2++);
printf("a的第二个字节 : %x\n", *p2++);
printf("a的第三个字节 : %x\n", *p2++);
printf("a的第四个字节 : %x\n", *p2++);

它的输出是:

a  : 12345678
a的第一个字节 : 78
a的第二个字节 : 56
a的第三个字节 : 34
a的第四个字节 : 12

通常我们不会把一个整型变量的值赋值给一个浮点型变量,因为我们直到两者的值是不同的。

但是,我们经常错误地把int指针类型变量的值赋值给short指针类型变量,因为我们想当然地认为都是指针类型,可以相互赋值。不同类型的指针类型之间 相互赋值(准确的说是把一种类型的指针变量的值赋值给另一种类型的指针变量),这需要进行强转,而且程序员自己承担这种强转带来的风险。当我们把int指 针类型变量的值赋值给unsigned int指针类型的变量时,编译器会给出一个警告。

总结一下:
1、指针变量的值是指针,而不是地址。
2、指针类型不是一种类型,而是一类类型的总称。
3、如果指向的变量类型不同,那么两种指针类型就属于不同的类型。
4、强转指针有风险,如果需要这么做,就要有充足的理由。
搜索更多相关主题的帖子: 编译器 C语言 空间 
2016-07-04 11:28
lanke711
Rank: 9Rank: 9Rank: 9
来 自:流浪在天国之路
等 级:蜘蛛侠
威 望:7
帖 子:317
专家分:1437
注 册:2015-7-16
收藏
得分:0 
都总结出来了。楼主辛苦了。。

普通人之所以普通,是因为他们普遍有一个通病,那就是认为自己永远普通。
千夫所指,我亦坚持。就算被所有人误解,我也照样守护这一切。
我们总是觉得,这些灵魂的表情,傲慢自大,目中无人,其实,真正目中无人的是我们。它们傲慢的不过是表情,而我们傲慢的却是行为!
记得,是为了忘记!
只要想着有那么一天,我就能忍受现在的每一天!
灾难并不可怕,可怕的是心中没有了希望。
你以为我在天堂,其实我正在路上。
当你觉得自己走不到终点的时候,请不要放弃。或许你的对手也是这种感觉。
2016-07-04 11:39
平常心q
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:120
专家分:550
注 册:2016-3-31
收藏
得分:0 
或许是自己理解有问题吧!看到最后,也没明白楼主的意思。若指针不能理解为地址,那指针到底是什么呢,楼主好像没说吧
2016-07-04 12:06
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
收藏
得分:0 
指针与地址的关系仁者见仁,智者见智。
只要你运用好指针,指针与地址是什么关系就按你自己的理解来好了。
多看看别人的总结,无论与你的想法是否相同,它总能让你反思。
可以看的出这是楼主用心去总结的

[此贴子已经被作者于2016-7-4 12:52编辑过]

收到的鲜花
  • w2383902016-07-05 11:13 送鲜花  1朵  
2016-07-04 12:51
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
收藏
得分:0 
简单的说,指针就是引用一个内存空间的东西,内存空间有起点有大小。仅仅说指针就是地址,是不合适的。不同的人确实有不同的看法,但有问题的看法会影响对指针的正确使用。有些人确实正确使用了指针,但有问题的表述会影响到其他人的理解。
2016-07-04 12:58
吹水佬
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:451
帖 子:10607
专家分:43186
注 册:2014-5-20
收藏
得分:0 
只要想到指针,同时也想到地址就可以了,指针是一个名堂,地址是指针的具体表现。



2016-07-04 14:58
低调低调
Rank: 3Rank: 3
来 自:四川省成都市
等 级:论坛游侠
威 望:1
帖 子:66
专家分:103
注 册:2016-6-23
收藏
得分:0 
各位大大幸苦了,但是我只想说我对指针还是晕的!怎么破!请问各位大大有什么好点的建议能让我最快的掌握指针吗?
2016-07-04 17:15
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
收藏
得分:0 
这个没有捷径,只能大量编程练习,自己感觉了。
2016-07-04 19:19
lanke711
Rank: 9Rank: 9Rank: 9
来 自:流浪在天国之路
等 级:蜘蛛侠
威 望:7
帖 子:317
专家分:1437
注 册:2015-7-16
收藏
得分:0 
不能够很好的理解指针的话,那看到指针就想到地址。实话,确实也是这样。看到指针,我也会想到地址这个东西。

普通人之所以普通,是因为他们普遍有一个通病,那就是认为自己永远普通。
千夫所指,我亦坚持。就算被所有人误解,我也照样守护这一切。
我们总是觉得,这些灵魂的表情,傲慢自大,目中无人,其实,真正目中无人的是我们。它们傲慢的不过是表情,而我们傲慢的却是行为!
记得,是为了忘记!
只要想着有那么一天,我就能忍受现在的每一天!
灾难并不可怕,可怕的是心中没有了希望。
你以为我在天堂,其实我正在路上。
当你觉得自己走不到终点的时候,请不要放弃。或许你的对手也是这种感觉。
2016-07-04 19:51
低调低调
Rank: 3Rank: 3
来 自:四川省成都市
等 级:论坛游侠
威 望:1
帖 子:66
专家分:103
注 册:2016-6-23
收藏
得分:0 
不是捷径   是可以快速掌握的一些程序,一些能最快掌握指针这个东西的程序  我只想照着多敲敲  因为这边书上和老师们讲的都是最基础的指针  让我没办法快速的掌握
2016-07-05 08:46
快速回复:指针与地址
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029231 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved