我是靠谱客的博主 不安红牛,最近开发中收集的这篇文章主要介绍C语言总结(指针)一、地址和指针二、指针变量三、指向数组的指针 ,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、地址和指针

一个计算机的内存由很多存储单元组成,这些存储单元是以字节为单位的一个连续存储空间。每个空间都有自己的内存单元编号。内存单元的编号即叫作地址,也称为指针。

在程序中定义了一个变量,在编译时系统就在内存中给这个变量分配了内存空间。系统会根据变量的类型,分配一定长度的空间。C系统为整型变量分配4个字节,为字符型变量分配1个字节

每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。

举个例子,程序中的语句“ int i =3 , int b =5 ; ”编译时系统分配内存编号为1000~1003的4个字节给 i ,内存编号为1004~1007的4个字节给 j ,并将数值3,5分别存入这两个区域,如图所示。

对变量值的存取时通过地址进行的。例如“ printf("%d",i); ”,执行过程是:根据变量名 i 与地址的对应关系,找到变量 i 的地址1000,然后从1000到1003的4个字节中取出数据(即变量的值3)输出。例如“ scanf("%d",&i); ”语句,就将键盘输入的值存入变量 i 对应的地址1000开始的整型存储区域。这种根据变量名对应的地址存取变量值的方式称为“ 直接访问 ”方式。

还有一种称为“间接访问”的方式,将变量 i 的地址存放在另一个内存单元中。C语言规定,在程序中可以定义一种特殊变量,用来存放地址。可以通过以下语句将 i 的地址存放到 p 中: p=&i;

这时 的值就是1000,即变量i所占用单元的起始地址,通常称为p指向了 i 。要存取变量 i 的值,也可以采用间接方式,先找到存放“ i 的地址”的单元地址( p 的地址),从中取出 i 的地址(1000),再到该地址中取出 i 的值(3)。如果有一个变量专门用来存放另一个变量的地址,则称它为指针变量。上述变量 p 就是一个指针变量。

二、指针变量

在程序定义变量后,系统会根据变量的类型,为变量在内存中分配多少字节的存储空间,最后确定变量的单元地址。有了变量的地址,就可以立即找到该变量所在的存储单元,并进行数据的存取操作。指针变量是专门存放变量地址的变量。

语法结构:  数据类型名 *指针变量名;      星号(*)为定义指针变量的标志,称为指针运算符。

例如: int *p;           表示定义指针变量p,它指向整数变量

例题:通过指针变量访问整数变量。

#include <stdio.h>
int main(){
	int a,b;
	int *p;  //定义指针变量p 
	a=5;
	p=&a;    //取a的地址 
	b=*p+5;	 //*p是取地址中的值 
	printf("a=%d,p=%d,b=%d",a,*p,b);
    return 0;
}

运行结果:  a=5,p=5,b=10

 &和*为单目运算符,优先级别仅次于括号和成员运算符,具有右结合性。运算符“ & ”的操作数允许是一般变量或指针变量,运算符“ * ”的操作数必须为指针变量或地址型表达式。

取地址符号与取值符号是互为逆运算:

#include <stdio.h>
int main(){
	int a=5;	  //定义a等于5 
	int *p;       //定义指针变量p 
	p=&a;    	  //取a的地址 
	printf("%d,%d,%dn",&a,p,&(*p));  //输出都是a的地址 
	printf("%d,%d,%dn",a,*p,*(&a));  //输出都是a的值 
	return 0;
}

&a 、p 、&(*p)取值是相同的,表示指针变量 p 存放的变量 a 的地址。

a 、*p 、*(&a)取值是相同的,表示指针变量 p 所指向的变量 a 的值。

指针变量必须先赋值,再使用。

三、指向数组的指针 

一个变量有地址,一个数组包含若干个元素,每个数组元素都在内存中占用存储单元,它们也有相应的地址。指针变量既然可以指向变量,当然也可以指向数组和数组元素。数组元素的指针即数组元素的地址。

数组名代表数组的起始地址,这是一个不允许赋值的指针(地址常量)。对数组元素的访问,既可以采用数组下标法( 如a[5] ),也可以采用指针法。指针法是通过数组元素的指针找到所需元素。使用指针法访问数组元素能使目标程序质量更高(占内存少,运行速度快)。

1.指向一维数组的指针

数组元素相当于一个普通变量,定义数组元素的指针与以前介绍的定义普通变量指针的方法相同。

例如:

int a[5];        //定义a为包含10个整型的数组
int *p;          //定义p为指向整数变量的指针变量
p = &a[0];       //将数组元素a[0]的地址赋值给指针变量p,p指向数组a中的a[0]元素
    

数组名a是数组的首地址, 它与&a[0]是同一值。因此p=&a[0]也可以写成p=a。

数组a不代表整个数组,“p=a”的作用是“把a数组的首地址赋给指针变量p” ,而不是“把数组a各元素的值赋给指针变量p ”。

2.数组指针的运算

指针变量p指向数组a的某个元素,p+1是指向数组的下一个元素(而不是将p的值加1)。

例如:

#include <stdio.h>
int main(){
	int a[3];        //定义数组a
	int *p;          //定义指针变量p
	p=a;             //a的首地址赋给指针变量p
	printf("%d,%d,%dn",p,p+1,p+2);
	printf("%d,%d,%dn",a,a+1,a+2);
	return 0;
}

运行结果
 

 数组元素是整型,每个元素占4个字节,p指向a[0],则p+1意味着使p的值加4个字节,使它指向下一个元素a[1]。p+1所代表的地址实际上是p+1*d,d是一个数组元素所占有的字节数。

a+i  和 p+i 是 a[i] 的地址;*(p+i)和*(a+i) 是 p+i和a+i 所指向的数组元素。

对于指针变量p,可以做以下运算: p++,p--,p+i,p-i,p+=i,p-=i 等。

指针也可以进行关系运算:

(1)若p1和p2指向同一个数组,则:

p1<p2表示p1指的元素在前;

p1>p2表示p1指的元素在后;

p1=p2表示p1与p2指向同一个元素。

(2)若p1和p2不指向同一个数组,比较毫无意义。

3. 指向二维数组的指针

1.二维数组元素的地址

与一维数组一样,二维数组名a是数组的首地址。 但二者不同的是,二维数据名的基类型不是数组元素类型,而是一维数据类型,因此,二维数组a是一个行指针。

例如二维数组 int a[3][4];  二维数组a的行指针、列指针和数组如下表:

 表中,二维数组a包含3个行元素:a[0],a[1],a[2],它们又都是一维数组名,因此也是地址常量;它们的类型与数组元素类型一致。a+1的值是数组 a 的起始地址加上1行元素占据的字节数的和,即a[1]的地址。a+i 的值是数组a的起始地址加上 i 行元素(4*i个整数)所占据的字节数的和,即 a[i] 的地址,所有称 a 为行指针。

a[0]是第0行的首地址;a[1]是第1行的首地址;a[2]是第2行的首地址。

a[0]+1是数组元素a[0][1]的地址,a[0]+2是数组元素a[0][2]的地址,a[1]+1是数组元素a[1][1]的地址。以此类推,任意数组元素a[ i ][ j ]的地址是a[ i ]+j,所有称a[ i ]为列指针。

二维数组元素的地址表示形式比较多,每种地址形式都有对应的数组元素引用方法。

如数组元素地址: &a [ i ] [ j ],a [ i ] + j,*( a + i ) + j

对应的数组元素为:a [ i ] [ j ],*( a [ i ] + j ),*( *( a+ i ) +j )

2.指向二维数组元素的指针变量(列指针)

二维数组是由若干行、若干列组成的。C语言中二维数组在内存中按照行顺序存放。因此在数组中,将一般简单变量的指针称作元素的指针。

当元素指针p指向某一个数组元素时,p+1将指向的下一个元素刚好是同行的下一列元素。因此,在对二维数组操作时,经常将元素指针称作列指针(下一个元素就是同行的下一列元素)。用列指针操作二维数组,只要知道二维数组中数组元素在内存中的存放顺序即可。

使用列指针输出二维数组元素:

#include <stdio.h>
int main(){
	int a[2][3]={{1,2,3},{4,5,6}},*p;
	for(p=a[0];p<a[0]+6;p++){
		if((p-a[0])%3==0){
			printf("n");
		}
		printf("%dt",*p);
	}
	return 0;
}

运行结果

3.指向二维数组元素的指针变量(行指针)

行指针p是用来存放地址的变量。当p指向二维数组a中的数组元素 a [ i ] [ j ] 时,p+1 将指向同列的下一行元素 a [ i + 1 ] [ j ],所有行指针不能按照一般指针变量的方法定义。行指针定义时,必须说明数组每行元素的个数。

        语法结构:  数据类型名  ( *指针变量名 )   [ 行元素个数 ];        例如: int (*p) [3];

该语句定义了一个指向每行3个整型元素的行指针p。p的基类型是一个包含3个整型元素的一维数组。如果有int a[4][3],则p与a的基类型相同,因此通常称p为指向二维数组的指针。

进一步的理解,行指针是指向列指针的指针变量,列指针为一级指针,行指针为二级指针。通过行指针确定数组元素所在的行首地址,通过列指针最后确定数组元素所在的列地址。

使用行指针输出二维数组元素:

#include <stdio.h>
int main(){
	int a[3][3]={1,2,3,4,5,6,7,8,9};
	int (*p) [3],i;
	for(p=a;p<a+3;p++){
		for(i=0;i<3;i++){
			printf("%dt",*(*p+i));
		}
		printf("n");
	}
	return 0;
} 

运行结果 

 分析: 这里把数组a看成一维数组,它的元素有a[0],a[1],a[2]。指针p与数组名a表示的地址常量的基类型相同,所有可以用p=a,使指针变量p指向数组a的第一个元素a[0],*p为a[0]的值,即为二维数组a中的第0行的首地址。*(*p+1)表示二维数组元素a[0][1]。还有其他方式表示二维数组元素a[i][j]:   *( *(p+i) +j )     *(a[ i ] + j )         *( *( a+i) +j )   

4.指针数组

如果一个数组的元素都是指针类型,则该数组称为指针数组,即数组的元素都是指针变量。

一维指针数组的定义形式为: 类型名  *数组名[ 常量表达式 ];

例如: int *p[5];

指针比较合适用来指向若干个字符串,使字符串处理更加方便灵活。

例如:图书馆的书有若干本书,想把书名放在一个数组中,对这些书进行排序和查询。

#include <stdio.h>
#include <string.h>
int main(){
	char *book[]={"Computer network","Vissual C++","Operating system","Data sturcture","Java"};
	int n=5,i,j,k;
	char *temp;
	for(i=0;i<n-1;i++){
		k=i;
		for(j=i+1;j<n;j++){
			if(strcmp(book[k],book[j])>0){
				k=j; 
			}
			if(k!=i){
				temp=book[i];
				book[i]=book[k];
				book[k]=temp;
			}
		}
	}
	for(i=0;i<n;i++){
		printf("%sn",book[i]);
	}
	return 0;	
} 

解析:strcmp是字符串比较函数,book[k]和book[j]是第k个和第j个字符串的起始地址。strcmp(book[k],book[j)的值为:如果book[k]所指向的字符串大于book[j]所指的字符串,函数值为正值;若相等,函数值为0;若小于,函数值为负值。if语句的作用是将两个字符串中“小”的那个字符串的序号(i或者j)保留在变量k中。执行完内循环for语句后,从第i个字符串到第n个字符串中,第k个字符串最“小”。如果k不等于i,那么最小的字符串不是第 i 串。因此,将book[i]和book[k]对换。

四、用指针变量作为函数参数

指针变量作为函数形参时,对应的实参必须为它提供确定的地址类型的表达式的值。通过函数中的形参指针,可以间接地访问实参地址中的数据。被调用函数如果向该地址单元赋给新的值,调用结束后主调函数可以使用这个数据。使用指针参数最重要的作用是,除了用return返回一个值之外,还可以通过指针参数返回多个数据。

例:指针变量作为形参,交换函数实参变量的值。

#include <stdio.h>
void swap(int *p,int *q){
	int t;
	t=*p;
	*p=*q;
	*q=t;	 
}
int main(){
	int a=3,b=5;
	printf("没使用函数前:a=%d,b=%dn",a,b);
	swap(&a,&b);
	printf("使用函数后:a=%d,b=%dn",a,b);
	return 0; 
}

运行结果 

五、返回指针值的函数 

一个函数可以返回一个整型值、字符值、实型值等,也可以返回指针型的数据,即地址。这种返回指针的函数一般定义形式为: 类型名  *函数名( 参数列表 );

例如 :  int *a( int x , int y );

a是函数名,调用它以后能得到一个指向整型数据的指针(地址)。()的优先级高于 * ,所以 a( int a ,int b )是函数,前面加个 * ,表示此函数是指针型函数(函数返回值是指针)。最前面的int表示返回的指针指向整型变量。

在使用函数返回指针类型时,要注意不能返回已经释放的内存地址。

 

最后

以上就是不安红牛为你收集整理的C语言总结(指针)一、地址和指针二、指针变量三、指向数组的指针 的全部内容,希望文章能够帮你解决C语言总结(指针)一、地址和指针二、指针变量三、指向数组的指针 所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部