求C语言中指针优点和注意事项说明(要有例子的) C语言指针**p是什么意思

作者&投稿:锐蚂 (若有异议请与网页底部的电邮联系)
Joel Spolsky认为,对指针的理解是一种aptitude,不是通过训练就可以达到的。虽然如此,我还是想谈一谈这个C/C++语言中最强劲也是最容易出错的要素。

鉴于指针和目前计算机内存结构的关联,很多C语言比较本质的特点都孕育在其中,因此,本篇和第六、第七两篇我都将以指针为主线,结合在实际编程中遇到的问题,来详细谈谈关于指针的几个重要方面。

指针类型的本质分析

1、指针的本质

指针的本质:一种复合的数据类型。下面我将以下面几个作为例子进行展开分析:

a)、int *p;
b)、int **p;
c)、int (*parValue)[3];
d)、int (*pFun)();

分析:

所谓的数据类型就是具有某种数据特征的东东,比如数据类型char,它的数据特征就是它所占据的内存为1个字节, 指针也很类似,指针所指向的值也占据着内存中的一块地址,地址的长度与指针的类型有关,比如对于char型指针,这个指针占据的内存就是1个字节,因此指针也是一种数据类型,但我们知道指针本身也占据了一个内存空间地址,地址的长度和机器的字长有关,比如在32位机器中,这个长度就是4个字节,因此指针本身也同样是一种数据类型,因此,我们说,指针其实是一种复合的数据类型,

好了,现在我们可以分析上面的几个例子了。

假设有如下定义:

int nValue;

那么,nValue的类型就是int,也就是把nValue这个具体变量去掉后剩余的部分,因此,上面的4个声明可以类比进行分析:

a)、int *

*代表变量(指针本身)的值是一个地址,int代表这个地址里面存放的是一个整数,这两个结合起来,int *定义了一个指向整数的指针,类推如下:

b)、int **

指向一个指向整数的指针的指针。

c)、int (*)[3]

指向一个拥有三个整数的数组的指针。

d)、int (*)()

指向一个函数的指针,这个函数参数为空,返回值为整数。

分析结束,从上面可以看出,指针包括两个方面,一个是它本身的值,是一个内存中的地址;另一个是指针所指向的物,是这个地址中所存放着具有各种各样意义的数据。

2、对指针本身值的分析

下面例子考察指针本身的值(环境为32位的计算机):

void *p = malloc( 100 );

请计算sizeof ( p ) = ?

char str[] = “Hello” ;
char *p = str ;

请计算sizeof ( p ) = ?

void Func ( char str[100])
{
请计算 sizeof( str ) = ? //注意,此时,str已经退化为一个指针,详情见
//下一篇指针与数组
}

分析:上面的例子,答案都是4,因为从上面的讨论可以知道,指针本身的值对应着内存中的一个地址,它的size只与机器的字长有关(即它是由系统的内存模型决定的),在32位机器中,这个长度是4个字节。

3、对指针所指向物的分析

现在再对指针这个复合类型的第二部分,指针所指向物的意义进行分析。

上面我们已经得到了指针本身的类型,那么将指针本身的类型去掉 “*”号就可得到指针所指向物的类型,分别如下:

a)、int

所指向物是一个整数。

b)、int*

所指向物是一个指向整数的指针。

c)、int ()[3]

()为空,可以去掉,变为int [3],所指向物是一个拥有三个整数的数组。

d)、int ()()

第一个()为空,可以去掉,变为int (),所指向物是一个函数,这个函数的参数为空,返回值为整数。

4、附加分析

另外,关于指针本身大小的问题,在C++中与C有所不同,这里我也顺带谈一下。

在C++中,对于指向对象成员的指针,它的大小不一定是4个字节,这主要是因为在引入多重虚拟继承以及虚拟函数的时候,有些附加的信息也需要通过这个指针进行传递,因此指向对象成员的指针会增大,不论是指向成员数据,还是成员函数都是如此,具体与编译器的实现有关,你可以编写个很小的C++程序去验证一下。另外,对一个类的静态成员(static member,可以是静态成员变量或者静态成员函数)来说,指向它的指针只是普通的函数指针,而不是一个指向类成员的指针,所以它的大小不会增加,仍旧是4个字节。
指针运算符&和*

“&和*”,它们是一对相反的操作,’&’取得一个物的地址(也就是指针本身),’*’得到一个地址里放的物(指针所指向的物)。这个东西可以是值(对象)、函数、数组、类成员(class member)等等。

参照上面的分析我们可以很好地理解&与*。

使用指针的好处?

关于指针的本质和基本的运算符我们讨论过了,在这里,我想再笼总地谈一谈使用指针的必要性和好处,为我们今后的使用和对后面篇章的理解做好铺垫。简而言之,指针有以下好处:

1)、方便使用动态分配的数组。

这个解释我放在本系列第六篇中进行讲解。

2)、对于相同类型(甚至是相似类型)的多个变量进行通用访问。

就是用一个指针变量不断在多个变量之间指来指去,从而使得非常应用起来非常灵活,不过,这招也比较危险,需要小心使用:因为出现错误的指针是编程中非常忌讳的事情。

3)、变相改变一个函数的值传递特性。

说白了,就是指针的传地址作用,将一个变量的地址作为参数传给函数,这样函数就可以修改那个变量了。

4)、节省函数调用代价。

我们可以将参数,尤其是大个的参数(例如结构,对象等),将他们地址作为参数传给函数,这样可以省去编译器为它们制作副本所带来的空间和时间上的开销。

5)、动态扩展数据结构。

因为指针可以动态地使用malloc/new生成堆上的内存,所以在需要动态扩展数据结构的时候,非常有用;比如对于树、链表、Hash表等,这几乎是必不可少的特性。

6)、与目前计算机的内存模型相对应,可按照内存地址进行直接存取,这使得C非常适合于一些较底层的应用。

这也是C/C++指针一个强大的优点,我会在后面讲述C语言的底层操作时,较详细地介绍这个优点的应用。

7)、遍历数组。

据个例子来说吧,当你需要对字符串数组进行操作时,想一想,你当然要用字符串指针在字符串上扫来扫去。

…实在太多了,你可以慢慢来补充^_^。
指针本身的相关问题

1、问题:空指针的定义

曾经看过有的.h文件将NULL定义为0L,为什么?

答案与分析:

这是一个关于空指针宏定义的问题。指针在C语言中是经常使用的,有时需要将一个指针置为空指针,例如在指针变量初始化的时候。
C语言中的空指针和Pascal或者Lisp语言中的NIL具有相同的地位。那如何定义空指针呢?下面的语句是正确的:

char *p1 = 0;
int *p2;
if (p != 0)
{
...
}
p2 = 0;

也就是说,在指针变量的初始化、赋值、比较操作中,0会被编译器理解为要将指针置为空指针。至于空指针的内部表示是否是0,则随不同的机器类型而定,不过通常都是0。但是在另外一些场合下,例如函数的参数原型是指针类型,函数调用时如果将0作为参数传入,编译器则不能将其理解为空指针。此时需要明确的类型转换,例如:

void func (char *p);
func ((char *)0);

一般情况下,0是可以放在代码中和指针关联使用的,但是有些程序员(数量还不少呦!也许就包括你在内)不喜欢0的直白,认为其不能表示作为指针的特殊含义,于是要定义一个宏NULL,来明确表示空指针常量。这也是对的,人家C语言标准就明确说:“ NULL应该被定义为与实现相关的空指针常量”。但是将NULL定义成什么样的值呢?我想你一定见过好几种定义NULL的方法:

#define NULL 0
#define NULL (char *)0
#define NULL (void *)0

在我们使用的绝大多数计算系统上,例如PC,上述定义是能够工作的。然而,世界上还有很多其它种类的计算机,其CPU也不是Intel的。在某些系统上,指针和整数的大小和内部表示并不一致,甚至不同类型的指针的大小都不一致。为了避免这种可移植性问题,0L是一种最为安全的、最妥帖的定义方式。0L的含义是: “值为0的整数常量表达式”。这与C语言给出的空指针定义完全一致。因此,建议采用0L作为空指针常量NULL的值。

其实 NULL定义值,和操作系统的的平台有关, 将一个指针定义为 NULL, 其用意是为了保护操作系统,因为通过指针可以访问任何一块地址, 但是,有些数据是不许一般用户访问的,比如操作系统的核心数据。 当我们通过一个空(NULL)的指针去方位数据时,系统会提示非法, 那么系统又是如何知道的呢??

以windows2000系统为例, 该系统规定系统中每个进程的起始地址(0x00000000)开始的某个地址范围内是存放系统数据的,用户进程无法访问, 所以当用户用空指针(0)访问时,其实访问的就是0x00000000地址的系统数据,由于该地址数据是受系统保护的,所以系统会提示错误(指针访问非法)。

这也就是说NULL值不一定要定义成0,起始只要定义在系统的保护范围的地址空间内,比如定义成(0x00000001, 0x00000002)都会起到相同的作用,但是为了考虑到移植性,普遍定义为0 。

2、问题:与指针相关的编程规则&规则分析

指针既然这么重要,而且容易出错,那么有没有方法可以很好地减少这些指针相关问题的出现呢?

答案与分析:

减少出错的根本是彻底理解指针。

在方法上,遵循一定的编码规则可能是最立竿见影的方法了,下面我来阐述一下与指针相关的编程规则:

1) 未使用的指针初始化为NULL 。

2) 在给指针分配空间前、分配后均应作判断。

3) 指针所指向的内容删除后也要清除指针本身。

要牢记指针是一个复合的数据结构这个本质,所以我们不论初始化和清除都要同时兼顾指针本身(上述规则1,3)和指针所指向的内容(上述规则2,3)这两个方面。

遵循这些规则可以有效地减少指针出错,我们来看下面的例子:

void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}

请问运行Test函数会有什么样的结果?

答:

篡改动态内存区的内容,后果难以预料,非常危险。因为free(str);之后,str成为野指针,if(str != NULL)语句不起作用。

如果我们牢记规则3,在free(str)后增加语句:

str = NULL;

那么,就可以防止这样的错误发生。

优点就是任何类型的指针都占4个bit(32位机)
而其他的形式不一定,float占4个,double占8个,char[1000]占1000个。
在函数中使用指针传递可以减少内存使用.....

本人刚刚开始学,直觉到了这么一点点区别。
不要见笑

C语言的指针有什么优缺点?~

1、指针的优点
是标识一块内存。电脑内存上的每一个字节都具有一个编号,称为地址(可以简单理解为指针),任何读写内存的指令都必须携带地址信息,否则电脑不知道读写那块内存。
不管程序是用什么语言写的,要运行数据和代码必须驻留内存,CPU要执行指令必须有一个“指针”程序计数器指向内存的代码块,如果某个指令要操作内存数据,该指令必须携带额外的地址信息。

2、指针的缺点
指针可以操作任何东西,所以指针很灵活、很强大,但也引入了复杂性。
扩展资料
1、指针利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。
2、输出一串字符时,只需要知道它的第一个字符的地址,就可以将这个字符串输出,而第一个字符的地址,可以用指针储存。所以有n个字符串时,就可以用n个指针来储存。
3、为了保存一个数据在内存中的地址,就需要指针变量。因此指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量。

**p表示p也表示地址,简单的说,这个地址对应的存储单元存储的数也是一个地址,而不是数值,而这个被存储的地址对应的存储单元存储的数据才是真正的相应类型的数值!
例如:
int i=10; //定义了一个整型变量
int *p=&i; //定义了一个指针指向这个变量
int **p1=&p; //定义了一个二级指针指向p指针
那么取出10的值方式为:
printf(“i=[%d]
”,*p);
printf(“i=[%d]
”,**p1);

扩展资料:
指针与数组关系
指针数组:就是一个由指针组成的数组,那个数组的各个元素都是指针,指向某个内存地址。 char *p[10];//p是一个指针数组
数组指针:数组名本身就是一个指针,指向数组的首地址。注意这是一个常数。
example:
char (*p)[10]//p是一个数组指针
函数指针:本身是一个指针,指向一个函数入口地址,通过该指针可调用其指向的函数,使用函数指针可实现回调函数。
参考资料来源:百度百科-指针

求C语言中指针优点和注意事项说明(要有例子的)
答:rt说明指针在使用中的优点和注意事项要有例子最好是以一个功能为例,有用指针实现的代码和不用指针实现的代码分如果嫌不够可以追加,不在乎分需要两段代码,一段用指针,一段不用实现... rt说明指针在使用中的优点和注意事项要有例子最好是以一个功能为例,有用指针实现的代码和不用指针实现的代码分如果嫌不够可...

急!!叙述对C语言指针的认识,在使用指针时应该注意什么问题? 谢谢大神...
答:int p(int); //从P 处起,先与()结合,说明P 是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数然后再与外面的int 结合,说明函数的返回值是一个整型数据 Int (*p)(int); //从P 处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里...

C语言中“指针”和“指针变量”的区别是什么??
答:1、概念不同 “指针”是概念,“指针变量”是具体实现,指针也是一个变量,所以需要进行定义,而对于指针的定义,与一般变量一样。2、 存放地址不同 一个变量的(内存)地址称为该变量的“指针”,通过指针能找到以它为地址的内存单元。而指针变量是用来存放另一个变量的地址的(即指针)。

c语言指针定义,有什么用,作用有
答:运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环, 能否正确理解和使用指针是是否掌握C语言的一个标志。同时, 指...

C语言中的指针到底有什么用
答:在C/C++中很灵活,但是也很危险,也很难学,如果指针指向错误的地址会引起程序崩溃,因此在C#中已经被微软封装了,但内部还是有指针的。如果有必要,C#中也可以使用指针,使用非安全代码,在项目生成选项卡中勾选“允许非安全代码”,然后就可以使用指针了,不过不建议这么做。unsafe { int a = 10;i...

论述C语言中指针的概念和作用,并举例说明
答:量,简言之,指针是用来存放地址的。2、作用:指向这个变量或数组的首地址,是变量的间接引用方式。其值如果改变,变量的值或数组元素的值也会跟着改变。程序对变量的操作实际上是对变量所在的存储空间读取和写入数据。方便对变量的操作。举例说明:int a=3;/*定义一个整型变量a,并赋初值3*/ int p...

c语言全面解析指针,十个知识点整理
答:C语言10个小知识了解指针 1.若有代码,int a=10,*p;p是指针:也是一个变量,且是一个只能用来存放地址的变量。2.若有代码,int a=10,*p;p=&a;当执行了上面的代码,会说“p指向了a”,其实就是“p指针变量存放了a的地址”。3.两个*的区别,有如下代码:inta=10,*p;//该处的* 说明p是...

C语言中,空指针的使用意义是什么?在编程中使用空指针会带来什么影响...
答:语言定义中说明, 每一种指针类型都有一个特殊值—— “空指针” —— 它与同类型的其它所有指针值都不相同, 它“与任何对象或函数的指针值都不相等”;不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。指针是个很强大的工具,可是正因为它太强大,所以要操作它不是件易事。操作...

C语言 指针做函数参数 的优点
答:现在来说说传参,其实你“为什么函数参数是字符串的多用指针?” 那句我不是很明白,C中的字符串传参好像就指针一种形式(除非用结构体)。何时用指针,何时用拷贝。当传的参数是一个结构体,而这个结构体比较大,这时最好用指针,因为如果用拷贝的话,单单花在拷贝的时间就要浪费很多,而如果这个...

c语言中的int指针是什么?
答:include<stdio.h> int main(){int num;double sum = 0;int count = 0;while(scanf("%d", &num) && num != -1)//输入-1停止} {sum += num;count++;} printf("%f", sum / count);return 0。