目录
前言
学习记录:C语言 指针篇
一、指向变量的指针
1.指针的概念
当我们定义一个变量时,系统会在内存中分配适当的存储空间,用以存储该变量的值。内存区的每一个字节有一个编号,这就是“地址”,它相当于旅馆中的房间号。在地址所标识的内存单元中存放的数据,就类似于在旅馆房间中居住的旅客一样。由于通过地址可以找到所需的变量单元,我们可以说,地址指向该变量单元。将地址形象化地称为“指针”。
一个变量的地址称为该变量的“指针”。如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”。指针是一个地址,而指针变量是存放地址的变量。
2.指针变量的定义和初始化
指针变量的定义
一般形式:数据类型(指针的目标变量的数据类型) *(表示定义指针变量,不是‘*’运算符)指针名(合法标识符)
注:
-
类型标识符可以是任何一种有效的数据类型标识符,是指针变量所指向的内存单元的数据类型,也称为基类型。
-
*号用在指针定义语句中表示该变量为指针变量。
-
指针变量名必须是合法的标识符。
-
指针变量与普通变量一样,使用之前不仅要定义,还必须赋予一个具体的值。未经赋值的指针变量的值是一个随机值,无法预知它会指向哪里,所以也称为“野指针”。
一般形式:[存储类型] 数据类型 *指针名=初始地址值
代码如下(示例):
int i,*p;
p=&i;
3.通过指针访问变量
- 注意“*” 的两个功能:
- 1.用于指针变量定义中,“*”是指针类型说明符,表示其后的变量是指针变量。
- 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+i和p+i表示的是数组中下标为i的元素a[i]的地址。
指针变量的赋值运算:
- p=&a; (将变量a地址→p)
- p=array; (将数组array首地址→p)
- p=&array[i]; (将数组元素地址→p)
- p1=p; (指针变量p值→p1)
- 不能把 一个整数→p, 也不能把p的值→整型变量
指针变量的算术运算:
指针变量的关系运算:
- 若p1和p2指向同一数组,则
- p1<p2 表示p1指的元素在前
- p1>p2 表示p1指的元素在后
- 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的相关内容,主要供自己学习复习