C语言 指针

目录

前言

一、指向变量的指针

1.指针的概念

2.指针变量的定义和初始化

3.通过指针访问变量

4.指针变量作为函数参数

5.指针的强制转换

6.void指针类型

二、指向数组的指针

1.指针变量与一维数组

2.多维数组元素的地址

3.指针变量与二维数组

4.数组指针作为函数参数

三、指针数组和指向指针的指针

指针数组的定义与使用

指针数组与字符串数组

指向指针的指针

 main函数的形参

四、指向函数的指针

函数指针的定义与使用

五、返回指针的函数

返回指针的函数定义与调用

六、指针应用程序,设计实例

总结


前言

学习记录:C语言 指针篇

一、指向变量的指针

1.指针的概念

当我们定义一个变量时,系统会在内存中分配适当的存储空间,用以存储该变量的值。内存区的每一个字节有一个编号,这就是“地址”,它相当于旅馆中的房间号。在地址所标识的内存单元中存放的数据,就类似于在旅馆房间中居住的旅客一样。由于通过地址可以找到所需的变量单元,我们可以说,地址指向该变量单元将地址形象化地称为“指针”。

一个变量的地址称为该变量的“指针”。如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”。指针是一个地址,而指针变量是存放地址的变量。

2.指针变量的定义和初始化

指针变量的定义

一般形式:数据类型(指针的目标变量的数据类型)   *(表示定义指针变量,不是‘*’运算符)指针名(合法标识符)

注:

  • 类型标识符可以是任何一种有效的数据类型标识符,是指针变量所指向的内存单元的数据类型,也称为基类型。

  • *号用在指针定义语句中表示该变量为指针变量。

  • 指针变量名必须是合法的标识符。

  • 指针变量与普通变量一样,使用之前不仅要定义,还必须赋予一个具体的值。未经赋值的指针变量的值是一个随机值,无法预知它会指向哪里,所以也称为“野指针”。

指针变量的初始化

一般形式[存储类型] 数据类型  *指针名=初始地址值

代码如下(示例):
int i,*p;
p=&i;

3.通过指针访问变量

  1. 注意“*” 的两个功能:
  2. 1.用于指针变量定义中,“*”是指针类型说明符,表示其后的变量是指针变量。
  3. 2.作为间接寻址运算符,用于表达式中,表示访问指针变量所指向的变量。

直接访问:按变量地址存取变量值

间接访问:通过存放变量地址的变量去访问变量值

4.指针变量作为函数参数

int main()
{   int a,b; 
	……
   int *pa=&a,*pb=&b;
    sort(pa,pb);
  //sort( &a , &b );
 ……
}
void sort(int *p1, int *p2)
{ int temp;
   if(*p1>*p2)
  { temp=*p1;     *p1=*p2;    *p2=temp;   }
   printf("p1=%d; p2=%d\n",*p1,*p2);
}

5.指针的强制转换

指针的强制类型转换格式为:(类型标识符 *)指针

例如:int a=1; int *pa=&a; float *pt;若是直接进行赋值:pt=&a;程序在编译时,会提示有不兼容的指针类型。正确完成上面要求的语句应该是:pt=(float *)&a; 或者pt=(float *)pa;

6.void指针类型

ANSI C定义了一种void类型指的针变量,表示定义一个指针变量,但不指定它指向何种类型的数据。void指针可以指向任意类型的数据,即可以用任意数据类型的指针对void指针变量进行赋值。void指针类型主要用来作为函数的形参,这样函数就可以接受任意数据类型的指针作为参数。

二、指向数组的指针

1.指针变量与一维数组

数组名是一个指针常量(地址常量),指向数组中第1个(下标为0)元素。对数组元素的访问是通过数组名加下标的方式来实现的。也可通过指针变量访问到数组中的元素。

代码如下(示例):

int a[10];
int *p;
p=a;  //或者p=&a[0];

说明:a+ip+i表示的是数组中下标为i的元素a[i]的地址。

指针变量的赋值运算:

  • p=&a;             (将变量a地址→p)
  • p=array;          (将数组array首地址→p)
  • p=&array[i];   (将数组元素地址→p)
  • p1=p;             (指针变量p值→p1)
  • 不能把 一个整数→p, 也不能把p的值→整型变量

指针变量的算术运算:

p++, p- -, p+i, p-i, p+=i,  p-=i 等

指针变量的关系运算:

  • 若p1和p2指向同一数组,则
  1.         p1<p2    表示p1指的元素在前
  2.         p1>p2    表示p1指的元素在后
  3.         p1==p2  表示p1与p2指向同一元素
  • 若p1与p2不指向同一数组,比较无意义

通过指针引用数组元素:

  • int  a[10], *p=a;
  • []:变址运算符;[ai]等价于*(a+i)
  • a[i]等价于p[i] 等价于*(p+i)等价于*(a+i)
  • a+i,p+i都是a[i]的地址;*(p+i),*(a+i),p[i]是a[i]
  • 数组名是地址常量,不可以进行自增自减运算

一维数组的引用方法小结:

 编写函数实现数组的逆序存放

#include<stdio.h>
#define N 10
int main()
{
  int i,array[N];
  ……
  inv ( array,N  );  
  ……	
  return 0;
}

void inv(int *p,int n)   //定义函数,形参为指针变量
{	
  int i,temp;
  for(i=0;i<n/2;i++) 
 {	 
     temp=p[i];
     p[i]=p[n-1-i];
     p[n-1-i]=temp;
  }
}
void main{
	int a[10];
	……
	inv(a,10);
	……
}
void inv(int x[ ],int n){
	int *p1,*p2,t;
	for(p1=x,p2=x+n-1; p1<p2; p1++,p2--){
		t=*p1;
		*p1=*p2;
		*p2=t;		
	}
}
void main{
	int a[10], *p=a;
	……
	inv(p,10);
	……
}
void inv(int  x[ ]  , int n){
	int *p1,*p2,t;
	for(p1=x,p2=x+n-1; p1<p2; p1++,p2--){
		t=*p1;
		*p1=*p2;
		*p2=t;		
	}
}

字符串与字符指针

(1)字符串的指针访问方法

a.用字符数组存储和访问字符串

char s[ ] ="Hello, World.";
printf("%s",s);
printf(“%s”, "Hello");

b.用字符指针访问字符串

字符串是一个指针常量,它的值是该字符串首字符的地址,可以定义一个字符指针变量,存储字符串指针常量

char *p ="Hello, World.";
printf("%s",p);

(2)字符指针变量与字符数组的区别

char str[10];

字符数组由若干个元素组成的,每个元素放一个字符,有确定的地址,str是指针常量。

char *ptr;

字符指针是一个接收字符串首地址的指针变量,不能将字符串放到字符指针变量中去。在对指针赋值前,它的值是不确定的。接受键入字符串时,必须指向事先先开辟好的存储空间(字符数组)

char str[10]=“hello”;

  • str是指针常量,值不能修改
  • str数组中的值可以修改

char *ptr=“hello”;//char *ptr = str;

  • ptr是指针变量,值可以修改。
  • ptr若指向字符串常量,则不能通过ptr修改字符串内容

(3)字符串中的字符存取方法

#include <stdio.h>
void main()
{
	char a[ ]="I am a boy.",b[20];
	int i;
  for(i=0;a[i]!='\0';i++)
		b[i]=a[i];
	b[i]='\0';
	printf("string a is:%s\n",a);
	printf("string b is:");
  for(i=0;b[i]!='\0';i++)
     printf("%c",b[i]);
	printf("\n");
}
#include <stdio.h>
void main()
{	char a[ ]=“I am a boy.”,b[20];
	char *p1,*p2;
     int i;
     p1=a;p2=b;
	for(;*p1!='\0';p1++,p2++)
        *p2=*p1;
	*p2='\0';
	printf("string a is:%s\n",a);
	printf("string b is:");
	printf("%s",b);
	printf("\n");
}

(4)字符指针做函数参数

#include <stdio.h>
void main() {
	void copy_string(char from[ ], char to[ ]);
	char a[ ]=“I am a teacher.”, b[ ]="you are a student.";
	printf("string a=%s\nstring b=%s\n",a,b);
	printf("copy string a to string b:\n ");
	copy_string(a,b);
	printf("\nstring a=%s\nstring b=%s\n",a,b);  
}

void copy_string(char from[ ], char to[ ]){
	int i=0;
	while(from[i]!='\0') {
		to[i]=from[i];  i++;
	}
	to[i]='\0';
} 

/*
void copy_string(char *from, char *to){
	while(*from!='\0') {
		*to=*from;  from++; to++ ;
	}
	*to='\0';
} 
*/

/*
void copy_string(char *from, char *to){
	while(*to++=*from++) {
    if(*from=='\0')
        break;
	}
} 
*/

例题:

(5)使用字符指针变量和字符数组的比较

  • 字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),决不是将字符串放到字符指针变量中。
  • 赋值方式。可以对字符指针变量赋值,但不能对数组名赋值
  • 初始化的含义
  • 存储单元的内容:编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元
  • 指针变量的值是可以改变的,而数组名代表一个固定的值(数组首元素的地址),不能改变
  • 字符数组中各元素的值是可以改变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的
  • 引用数组元素:对字符数组可以用下标法和地址法引用数组元素(如:a[5],*(a+5))。如果字符指针变量p=a,则也可以用指针变量带下标的形式和地址法引用(如:p[5],*(p+5))
  • 用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串:char *format;format=“a=%d,b=%f\n”; printf(format,a,b);相当于printf(“a=%d,b=%f\n”,a,b);

2.多维数组元素的地址

3.指针变量与二维数组

(1) 行指针与列指针

 

 

 

表示形式

含义

地址

a

二维数组名,数组首地址

2000

a[0],  *(a+0),  *a

0行第0列元素地址

2000

a+1&a[1]

1行首地址

2016

a[1],  *(a+1)

1行第0列元素地址

2016

a[1]+2,  *(a+1)+2,  &a[1][2]

1行第2列元素地址

2024

*(a[1]+2), *(*(a+1)+2), a[1][2]

1行第2列元素值

13

(2)通过行指针变量访问二维数组

定义形式:  数据类型   (*指针名)[一维数组维数];

例    int   (*p)[4];

  • ( )不能少,int (*p)[4]与int *p[4]不同
  • p的值是一维数组的首地址,p是行指针
  • 可让p指向二维数组某一行,如:int  a[3][4],(*p)[4]=a;
  • 一维数组指针变量维数和二维数组列数必须相同

  • //通过行指针变量完成对二维数组的输出
    #include <stdio.h>
    int main() 
    {
       int i,j,a[2][3]={{1,2,3},{4,5,6}},(*p)[3]=NULL;
       p=a;//给行指针变量p赋值
       for(i=0;i<2;i++)
       {
         for(j=0;j<3;j++)
      	 printf("a[%d][%d]=%d",i,j,p[i][j]);//输出二维数组元素*(p[i]+j),*(*(p+i)+j),(*(p+i))[j]
         printf("\n");//输完一行后换行输出下一行
       }
       return 0;
    }
    
    //通过列指针变量完成对二维数组的输出
    #include <stdio.h>
    int main() 
    {
     int i, j, a[2][3]={{1,2,3},{4,5,6}}, *p=NULL;
     p=&a[0][0];//p=a[0],p=*a
     for(i=0;i<2;i++)        
     {
       for(j=0;j<3;j++)	
         printf("a[%d][%d]=%d",i,j,*(p+i*3+j));
       printf("\n");
     }
     return 0;
    }

    4.数组指针作为函数参数

  • //利用数组指针作为函数参数,对数组元素的输入输出
    int main()
    {
        int a[2][3],(*p)[3];
        p=a;	
        ArrayIn(p,2);
        ArrayOut(a,2);
        return 0 ;
    }
    void ArrayIn(int (*p)[3],int n)  
    {
        int i,j;
        printf("please input int numbers:\n" );
        for(i=0;i<n;i++)	
            for(j=0;j<3;j++)	
                scanf("%d",&p[i][j]);	
    }
    void ArrayOut(int (*p)[3],int n)
    {
        int i,j;
        for(i=0;i<n;i++)
        {
            for(j=0;j<3;j++)
            printf("a[%d][%d]=%d ",i,j,p[i][j]);    
            printf("\n");
        }
    }
    #include <stdio.h>
    int main()
    { void search(float (*p)[4],int n); 
      float score[3][4]={{65,57,70,60},{58,87,90,81},{90,99,100,98}}; 
      search(score,3); 
      return 0;
    }
    void search(float (*p)[4],int n) 
    {
        int i,j,flag;
        for(j=0;j<n;j++)
        {
            flag=0;
            for(i=0;i<4;i++)
            if(*(*(p+j)+i)<60) flag=1;
            if(flag==1)
            {
                printf("No.%d fails\n",j+1);
                for(i=0;i<4;i++)
                    printf(“%5.1f ”,*(*(p+j)+i));                
                printf("\n");
            }
        }
    }

三、指针数组和指向指针的指针

指针数组的定义与使用

(1)指针数组的定义

定义形式:类型 *数组名[大小];

  • int  i;
  • int  a[10];
  • a是一个数组,它有10个元素,每个元素的类型都是整型
  • int *p;
  • int *pa[10];
  • pa是一个数组,它有10个元素,每个元素的类型都是整型指针

(2)使用指针数组访问二维数组

(3)指针数组与数组指针的区别

指针数组数组指针
定义形式int *p[3]int (*p)[3]
变量性质p为数组名,是指针常量,数组的元素是指针p是指针变量,指向一个一维数组

指针数组与字符串数组

(1)一个字符串的存储与访问

 (2)多个字符串的存储与访问

 (3)二维数组与指针数组区别

(4)将若干字符串按字母顺序(由小到大)输出

#include <stdio.h>
#include <string.h>
void sort(char *name[],int n);
void print(char *name[],int n);
int main()
{
	int n=4; 
	char *name[]={“Follow”,“Great”,“FORTRAN”,“Computer”};
 	sort(name,n); 
	print(name,n); 
	return 0;
}
void sort(char *name[],int n) 
{
	char *temp;
	int i,j,k;
	for (i=0;i<n-1;i++) 
	{
		k=i;
		for (j=i+1;j<n;j++)
			if(strcmp(name[k],name[j])>0) k=j;
		if (k!=i)
		{
			temp=name[i];
 			name[i]=name[k];
			name[k]=temp;
		}
	} 
}
void print(char *name[],int n) 
{
	int i;
	for(i=0;i<n;i++)
		printf(“%s\n”,name[i]);
}
/*
void print(char *name[],int n)
{
    int i=0;
    char *p;
    p=name[0];
    while(i<n)
    {
        p=*(name+i);
        i++;
        printf("%s\n",p);
    }
}
*/

指向指针的指针

 

 main函数的形参

四、指向函数的指针

函数指针的定义与使用

//通过指针变量访问它所指向的函数
#include<stdio.h> 
int main()
{
    int max(int,int);
    int a,b,c; 
    int (*p)(int,int);//只能指向函数返回值为整型且有两个整型参数的函数
    p=max;//必须先指向被调函数,不能写成p=max(a,b)
    printf("please enter a and b:");
    scanf("%d,%d",&a,&b);
    c=(*p)(a,b);
    printf(“%d,%d,max=%d\n",a,b,c);
    return 0;
}
int max(int x,int y) 
{
    int z;
    if(x>y) z=x;
    else z=y;
    return(z);
}

五、返回指针的函数

返回指针的函数定义与调用

 

六、指针应用程序,设计实例


总结

以上就是C语言指针相关的内容,简单介绍指针的相关知识,参考了PPT的相关内容,主要供自己学习复习

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值