目录
1,指针本身是一个地址,以int的形式保存
(32位用四个字节储存,64位操作系统用八个字节储存)
2,指针的赋值
一般来说指针是无法直接赋值的
当然可以用这种形式来强制赋值
(int*) p = 101;
2.1C语言允许指针赋值为0(初始化)
int* a = 0;
常用 :(防止未初始化指针破化内存
if ( p != 0 )
*p+1=xxxx;
宏定义
#define NULL 0
在条件语句里初始化也不行,会报错,如
#include<stdio.h>
//输入a和b两个整数,按先大后小的顺序输出a和b
int main()
{
int a, b;
int* p_a, *p_b;
scanf_s("%d %d", &a, &b);
if (a < b)
{
p_a = &b;
p_b = &a;
}
if(a>=b)
{
p_a = &a;
p_b = &b;
}
printf("a=%d,b=%d", *p_a, *p_b);
return 0;
}
正确操作:
#define NULL 0
#include<stdio.h>
//输入a和b两个整数,按先大后小的顺序输出a和b
int main()
{
int a, b;
int* p_a=NULL, *p_b=NULL;//初始化
scanf_s("%d %d", &a, &b);
if (a < b)
{
p_a = &b;
p_b = &a;
}
if(a>=b)
{
p_a = &a;
p_b = &b;
}
printf("a=%d,b=%d", *p_a, *p_b);
return 0;
}
2.2指针赋值例
#include<stdio.h>
void main()
{
char c = '9', * sp1, * sp2;
sp1 = &c; sp2 = sp1;
printf("%c", *sp2);
}
2.3输出指针的值
pointer_1=&a; //把变量a的地址赋给指针变量pointer_1
pointer_2=&b; //把变量b的地址赋给指针变量pointer_2
printf("a=%d,b=%d\n",a,b); //输出变量a和b的值
printf("*pointer_1=%d,*pointer_2=%d\n",*pointer_1,*pointer_2);
//输出变量a和b的值
3,用指针引用数组
当我们定义一个数组时
int a[100]={};
a是数组的首地址,且是以常量指针的形式保存(不能通过a++等来更改
所以当我们针对数组进行一些操作时,通常将之复制到变量指针(P)上。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
//输入
int a[10] = {};
int* p = a;
for (int i = 0; i < 10; i++)
{
scanf("%d", p++);
//恢复指针
p = a;
//输出
for (int i = 0; i < 10; i++)
{
printf("%d\n", *p++);
}
return 0;
}
注意经过一系列 的p++会使得p指向数组的末位。需要读取数组需要重新使指针指向数组的首地址
3.1优先级问题
++和*为同优先级
从左到右依次执行
3.2用数组名作为函数形参
int main()
{ void fun(int arr[], int n); //对fun函数的声明
int array[10]; //定义array数组
⋮
fun(array,10); //用数组名作函数的参数
return 0;
}
void fun(int arr[], int n) //定义fun函数
{
⋮
}
3.4.多维数组
#include <stdio.h>
int main()
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
printf("%d,%d\n",a,*a); //0行起始地址和0行0列元素地址
printf("%d,%d\n",a[0],*(a+0)); //0行0列元素地址
printf("%d,%d\n",&a[0],&a[0][0]); //0行起始地址和0行0列元素地址
printf("%d,%d\n",a[1],a+1); //1行0列元素地址和1行起始地址
printf("%d,%d\n",&a[1][0],*(a+1)+0); //1行0列元素地址
printf("%d,%d\n",a[2],*(a+2)); //2行0列元素地址
printf("%d,%d\n",&a[2],a+2); //2行起始地址
printf("%d,%d\n",a[1][0],*(*(a+1)+0)); //1行0列元素的值
printf("%d,%d\n",*a[2],*(*(a+2)+0)); //2行0列元素的值
return 0;
}
//有一个3×4的二维数组,要求用指向元素的指针变量输出二维数组各元素的值。
#include <stdio.h>
int main()
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p; //p是int *型指针变量
for(p=a[0];p<a[0]+12;p++) //使p依次指向下一个元素
{ if((p-a[0])%4==0) printf("\n"); //p移动4次后换行
printf("%4d",*p); //输出p指向的元素的值
}
printf("\n");
return 0;
}
//输出二维数组任一行任一列元素的值。
#include <stdio.h>
int main()
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; //定义二维数组a并初始化
int (*p)[4],i,j; //指针变量p指向包含4个整型元素的一维数组
p=a; //p指向二维数组的0行
printf("please enter row and colum:");
scanf("%d,%d",&i,&j); //输入要求输出的元素的行列号
printf("a[%d,%d]=%d\n",i,j,*(*(p+i)+j)); //输出a[i][j]的值
return 0;
}
4.字符串
4.1通过指针引用字符串
#include <stdio.h>
int main()
{ char string[]="I love China!"; //定义字符数组sting
printf("%s\n",string); //用%s格式声明输出string,可以输出整个字符串
printf("%c\n",string[7]); //用%c格式输出一个字符数组元素
return 0;
}
相当于
#include <stdio.h>
int main()
{ char *string="I love China!"; //定义字符指针变量string并初始化
printf("%s\n",string); //输出字符串
return 0;
4.2字符串的复制
#include <stdio.h>
int main()
{ char a[]="I am a student.",b[20]; //定义字符数组
int i;
for(i=0;*(a+i)!='\0';i++)
*(b+i)=*(a+i); //将a[i]的值赋给b[i]
*(b+i)='\0'; //在b数组的有效字符之后加'\0'
printf("string a is:%s\n",a);//输出a数组中全部有效字符
printf("string b is:");
for(i=0;b[i]!='\0';i++)
printf("%c",b[i]); //逐个输出b数组中全部有效字符
printf("\n");
return 0;
}
#include <stdio.h>
int main()
{ char a[]="I am a boy.",b[20],*p1,*p2;
p1=a;p2=b;
//p1,p2分别指向a数组和b数组中的第一个元素
for(;*p1!='\0';p1++,p2++) //p1,p2每次自加1
*p2=*p1;
//将p1所指向的元素的值赋给p2所指向的元素
*p2='\0'; //在复制完全部有效字符后加'\0'
printf("string a is:%s\n",a); //输出a数组中的字符
printf("string b is:%s\n",b); //输出b数组中的字符
return 0;
}
5.函数中对指针的应用
5.1将指针变量作为函数参数
5.1.1指针的定义
定义函数时需要同时定义指针变量
void swap(int *p1,int *p2)
{
...
}
值得注意的是:如下的*temp不指向变量而直接赋值,由于temp指向位置为随机,可能会覆盖原有数据,计算机并不允许此类操作
//错误示范
void swap(int *p1,int *p2)
{ int *temp;
*temp=*p1;
*p1=*p2;
*p2=*temp;
}
5.1.2指针的引用
不需要加*
swap(pointer_1,pointer_2);
5.2将数组传递至函数中
void inv(int x[],int n) //形参x是数组名
{ int temp,i,j,m=(n-1)/2;
for(i=0;i<=m;i++)
{ j=n-1-i;
temp=x[i]; x[i]=x[j]; x[j]=temp; //把x[i]和x[j]交换
}
return;
}
void inv(int *x,int n) //形参x是指针变量
{ int *p,temp,*i,*j,m=(n-1)/2;
i=x; j=x+n-1; p=x+m;
for(;i<=p;i++,j--)
{ temp=*i; *i=*j; *j=temp;} //*i与*j交换
return;
}
5.3.返回指针的函数
int *a(int x,int y);
x和y是函数的形参,调用函数可以返回一个Int*型指针
we must return an adress ##
float *search(float (*pointer)[4],int n)
//形参pointer是指向一维数组的指针变量
{ float *pt;
pt=*(pointer+n); //pt的值是&score[k][0]
return(pt);
}
//将数组a中n个整数按相反顺序存放。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int arra[3];
int main()
{
int a[] = { 9,8,7};
int* p1;
int *func(int arr[]);
p1 = func(a);
for (int i = 0; i < 3; i++)
{
printf("%d\n",* p1++);
}
return 0;
}
int *func(int arr[])
{
int* p=arr,*p2=arra;
p = p + 2;
for (int i = 0; i < 3; p--, p2++,i++)
{
*p2 = *p;
}
p2 = arra;
return p2;
}
6. *指针数组和多重指针
6.1指针数组
类型名 *数组名[数组长度];
int *p[4];
实例:将若干字符串按字母顺序(由小到大)输出。
//将若干字符串按字母顺序(由小到大)输出。
#include <stdio.h>
#include <string.h>
int main()
{ void sort(char *name[],int n); //函数声明
void print(char *name[],int n); //函数声明
char *name[]={"Follow me","BASIC",
"Great Wall","FORTRAN","Computer design"};
//定义指针数组,它的元素分别指向5个字符串
int n=5;
sort(name,n); //调用sort函数,对字符串排序
print(name,n); //调用print函数,输出字符串
return 0;
}
void sort(char *name[],int n) //定义sort函数
{ 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) //定义print函数
{ int i;
for(i=0;i<n;i++)
printf("%s\n",name[i]);
//按指针数组元素的顺序输出它们所指向的字符串
}