Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141904
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 265
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-04 13:11
文章分类

全部博文(29)

文章存档

2015年(2)

2014年(27)

我的朋友

分类: C/C++

2014-01-09 17:37:58

C语言中指针的用法

指针和结构体一直是C语言的难点,如果搞不明白看代码时会很困难,这几天决定重新捡起《C primer pius》,复习一下相关知识,虽然能看懂,但对我来说写出相应的代码还是有困难的,以后必须要多动手。

1指针的定义

指针是一个数值为地址的变量。

如果你将指针变量命名为ptrptr=&pooh,对于这个语句,我们称ptr指向pooh,同时可以使用间接运算符*来获取pooh中存放的数值。

例如:     pooh=22;

ptr=&pooh;

val=*ptr;

2指针的声明

int *ptr;

类型标示符表明了被指向变量的类型,(*)表示该变量为一指针,声明int *ptr;意思是ptr是一个指针,且*ptrint类型。prt的值是一个地址,它有一个无符号整数表示,ANSI C专门为指针提供了%p的输出格式。

当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并不分配用来存储数据的内存空间。因此*prt = 5;是错误的,不能对未初始化的指针取值。

3指针与数组的关系

由于数组名同时也是该数组元素的首地址,也就是说,如果date是一个数组,则date==&date[0],两者都代表首元素的内存地址。在C中,对一个指针加1的结果是对该指针加一个存储单元,对于数组而言,地址会增加到下一个元素的地址,这就是为什么在声明指针时必须要声明它所指向对象的类型。

例如:     dates + 2 == &date[2]               /*相同的地址*/

              *(dates + 2) == dates[2]           /*相同的值*/

下面是使用指针参数的例子

例1:

#include "stdio.h"

#define SIZE 5

int sump(int *start,int *end);

int main(void)

{

         int a[SIZE] = {5,10,15,20,25};

         int answer;

         answer = sump(a,a+SIZE);

         printf("The total number of a is %d.\n",answer);

         return 0;

}

int sump(int *start,int *end)

{

         int total = 0;

         while(start < end)

         {

                   total = total + *start;

                   start++;

         }

         return total;

}

由于指针start最初指向a的首元素,执行完赋值语句后,start++使指针指向下一个元素,start1时它将增加一个int大小,a+SIZE为数组结尾后的下一个元素,因此,处理的最后一个元素将是end所指向的位置之前的元素。

4指针与二维数组



通过下面例子的输出可以得出指针与二维数组的关系

例2:

#include "stdio.h"

int main(void)

{

         int zippo[4][2] = {{1,3},{5,7},{2,4},{6,8}};

         int (*pz)[2];   //pz指向一个包含2个int值的数组

         pz = zippo;

         printf("pz = %p,pz+1 = %p\n",pz,pz+1);

         printf("pz[0] = %p,pz[0]+1 = %p\n",pz[0],pz[0]+1);

         printf("*pz = %p,*pz+1 = %p\n",*pz,*pz+1);

         printf("*pz[1] = %d,*(*pz+1) = %d\n",*pz[1],*(*pz+1));

         printf("*(*(pz+2)+1) = %d\n",*(*(pz+2)+1));

         return 0;

}

5定义字符串中,数组与指针的差别

通过下面的例子可以发现,声明字符串可以用数组形式和指针形式,数组的初始化是从静态存储区把一个字符串复制给数组,指针初始化只是复制字符串的地址,两者的主要差别是,数组名al是个常量,指针head是个变量,两者都可以使用数组符号和指针加法,但只有指针可以使用增量运算符。

当改变head字符串中的值时,编辑器会出错,所以它的值是不允许改变的,一般可以加上const修饰符,而数组形式则不需要,因为数组从最初的字符串得到一个拷贝。

例3:

#include "stdio.h"

int main(void)

{

         int i;

         const char *head = "abcde";

         char al[] = "abcde";

         for(i=0;i<5;i++)

         {

                   putchar(al[i]);

                   putchar(*(al+i));

         }

         putchar('\n');

         for(i=0;i<5;i++)

         {

                   putchar(head[i]);

                   putchar(*(head+i));

         }

         putchar('\n');

while(*(head)!='\0')

         putchar(*(head++));        

         return 0;

}

6字符串数组

使用字符串数组,可以使用下标来访问多个不同的字符串

例如下面的声明:

const char *al[3] = {“abc”,”def”,”ghi”};

al是一个由三个指向char指针组成的数组,数组里的每一个元素都是一个char类型的地址,第一个指针是al[0],它指向第一个字符串的第一个字符。

*al[0] == ‘a’   *al[1]+1 == ‘e’    al[2][1] == ‘h’

7指向结构的指针

7.1 结构指针的声明

结构指针的声明很简单:struct guy *him;

这个声明不是为了建立一个新的结构,而是意味着指针him可以指向任何现有的guy类型结构,例如如果bar是一个guy类型结构,him = &bar 跟数组不同一个结构的名字不是该结构的首地址,必须使用&运算符,当al是一个结构数组,him = &al[0] ,him+1指向al[1]

如何来使用指针访问成员?

假设him == &bar则bar.income == (*him).income == him->income

7.2 两种作函数参数的方法

用结构的地址作为函数的参数,注意函数的声明,函数调用,函数形参的写法。使用指针作为参数的优点是执行起来很快,缺点是缺少对数据的保护,如果在showinfo()函数中写入了改变结构中任何成员的代码,编译器会捕获这个错误,因此使用const则能避免。用结构作为参数传递的优点是函数处理的是原始数据的副本,这样会更安全,编程风格也会更加清晰。

例4:用结构指针作为参数

#include "stdio.h"

#define SIZE 10

struct book {

         char al[SIZE];

         int k;

};

void getinfo(struct book *);

void showinfo(struct book *);

int main(void)

{

         struct book person;

         getinfo(&person);

         showinfo(&person);

         return 0;

}

void getinfo(struct book *pst)

{

         printf("please enter your name\n");

         gets(pst->al);

         printf("please enter the number\n");

         scanf("%d",&(pst->k));

}

void showinfo( const struct book *pst)

{

         printf("%s have %d books\n",pst->al,pst->k);

}

例5:用结构作为参数和返回值

#include "stdio.h"

#define SIZE 10

struct book {

         char al[SIZE];

         int k;

};

struct book getinfo(void);

void showinfo(struct book);

int main(void)

{

         struct book person;

         person = getinfo();

         showinfo(person);

         return 0;

}

struct book getinfo(void)

{

         struct book temp;

         printf("please enter your name\n");

         gets(temp.al);

         printf("please enter the number\n");

         scanf("%d",&(temp.k));

         return temp;

}

void showinfo(struct book info)

{

         printf("%s have %d books\n",info.al,info.k);

}

7.3在结构中使用字符数组还是字符指针

         从语法上看,两者都可以,但是使用字符指针更容易出错,当用字符数组时字符串储存在结构的内部,使用字符指针时,结构中存放的只是两个地址,并不为字符串分配任何空间,字符指针应该只能用来管理那些已经创建的而且已经分配过内存的字符串。

         因此,如果需要一个结构来存储字符串,一般使用字符数组。下面是字符指针的声明

struct book {

           char *first;

    char *last

};

8函数与指针

8.1函数指针

函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。函数指针有两个用途:调用函数和做函数的参数。

      当声明一个函数指针时,必须声明它指向的函数类型,例如,声明一个无返回值,函数参量为char*的函数:void toupper(char *);要声明指向这类函数的指针pf,则声明为:void *pf(char *);  pf是一个指向函数的指针,可使用表达式(*pf)代替toupper(函数名),由于函数名可以用来表示函数的地址,所以pf == toupper(地址)可使用pf表示函数地址。函数指针最普遍的用法之一是作为函数的参数,例如,考虑以下函数原型:void show (void (*fp)(char *),char * str);使用下面的函数调用,show(fp,mis);

例6:使用函数指针把字符串转换为大写

#include "stdio.h"

#include "ctype.h"

void Toupper(char *);

void show(void (* fp)(char *),char *str);

int main(void)

{

         char copy[6] = "abcde";

         void (*pfun)(char *);

         pfun = Toupper;

         show(pfun,copy);

         return 0;

}

void Toupper(char *str)

{

         while(*str)

         {

                   *str = toupper(*str);

                   str++;

         }

}

void show(void (* fp)(char *),char *str)

{

         (*fp)(str);

         puts(str);

}

8.2指针函数

指针函数,指针函数是指带指针的函数,即本质是一个函数。函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。声明一个指针函数,int *pfun(int, int);由于“*”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。接着再和前面的“*”结合,说明这个函数的返回值是一个指针。由于前面还有一个int,也就是说,pfun是一个返回值为整型指针的函数。经常使用在返回数组的某一元素地址上。

例7:输入第几个学生并打印他的成绩

#include "stdio.h"

int *find(int (*pionter)[3],int n);

int main(void)

{

         static int score[][3] = {{60,70,80},{61,71,81},{62,72,82}};

         int *p;

         int m,i;

         printf("enter the student to be found\n");

         scanf("%d",&m);

         printf("the score of NO.%d are:\n",m);

         p = find(score,m-1);

         for(i=0;i<3;i++)

         {

                   printf("%d\t",*(p+i));

         }

         return 0;

}

int *find(int (*pionter)[3],int n)

{

         int *pt;

         pt = *(pionter+n);

         return pt;

}

 

 

阅读(1633) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~