C语言—指针(针对小白版)
一、基本概念
1、指针是具有指向(指内存单元)含义的数据,指针就是地址(内存单元的编号)
2、C语言处理指针数据:定义指针类型---对应处理的数据,是指针(地址)这种数据
3、定义指针类型变量
基类型 *指针变量名;
//基类型:代表的是一个数据类型(整型、字符型、浮点型、数组类型)
//* :定义指针变量时,*只是修饰作用(代表当前定义的不是普通变量,而是指针类型的变量)
//指针变量名:标识符基类型含义: 表示[指针变量名]中“地址”指向的“内存空间”上对应的数据类型
4、p是指针类型数据,int * 表示这是指向int型数据的一类指针
int *p=&a; //p指向了a(这里*只是修饰作用,没有做运算)5、 a空间的访问:通过a访问——直接访问,通过p访问——间接访问。
6、*p运算过程
- 拿出p中的地址值,到内存中定位
- 从定位处开始,向下偏移sizeof(基类型)大小的一块空间
- 将这块空间当做一个基类型数据或变量来看
7、举例说明
int a=0x12345678;
short *p=&a;
printf("*p=%#x\n",*p);a 是int型——占4个字节——数据为0x12345678
p 是short*指针类型——p要指向的目标类型是short类型
&a 表示获得一个(int *)类型的地址值
在64位的平台上,所有的指针类型都是64位,8个字节
0x12345678,自小到大:0x78,0x56,0x34,0x12
8、考点:判断电脑大小端
1 #include<stdio.h> 2 int isLittleEdian(void)3 {4 unsigned int a=1; //a=1放在低位数据(1 0 0 0)5 unsigned char *p=(unsigned char *)&a;6 7 return *p; // 8 }
小端返回1,大端返回0;
二、指针的作用
1、被调修改主调
实现:函数传参时必须传的是地址;被调函数中必须有对应的*p(指针的间接访问)的运算
2、函数可以通过指针带出多个结果
#include<stdio.h>
void maxTwo(int x,int y,int *max,int *min)
{if(x>y){*max=x;*min=y;}else{*max=y;*min=x;}
}
int main()
{int a,b,max,min;scanf("%d %d",&a,&b); maxTwo(a,b,&max,&min);printf("max=%d,min=%d\n",max,min); return 0;
} 三、指针的运算
1、p+N
表示指向了下一个基类型(相当于跳过了一个基类型)
值的大小是相当于加了一个N*sizeof(基类型)
2、p++
表示指向了下一个基类型(相当于跳过了一个基类型)
值的大小是相当于加了一个1*sizeof(基类型)
3、p-q
p和q必须是同类型的指针
结果表示相差了几个基类型
4、指针不能做(*)(/)(+)
5、指针也可以做关系运算
四、指针操作数组
1、因为数组是一片连续的内存空间,所以指针操作数组只需要知道数组首元素的地址即可
int a[10]={1,2,3,4,5,6,7,8,9,10};&a[10]; //&a[10]取了一个存放int类型数据的空间的地址int * p=&a[10];
int * p=a;2、数组下标的运算方式,最终还是转换了指针实现
a[i] <=> *(p+i)3、函数中如果传递数组,只需要传递首元素的地址即可
4、指针打印数组(简便)
void printArray(int *begin int *end)
{while(begin<=end){printf("%d\n",*begin);begin++;}
}printfArray(a,a+len-1);
五、快速排序
思想:分而自治
step1:找到一个基准值 //数组的第一个元素作为基准值
step2:从右边开始,比基准值小的第一个值
1 #include<stdio.h>2 void printArray(int *a,int len)3 {4 for(int i=0;i<len;i++) 5 {6 printf("%d\n",*(a+i));7 }8 }9 void swap (int *begin, int *end)10 {11 int temp=*begin;12 *begin=*end;13 *end=temp;14 }15 void quickSort(int *begin,int *end)16 {17 int *p=begin;18 int *q=end;19 20 if (begin>=end)21 {22 return ;23 }24 25 int *k=begin;26 while(begin<end)27 {28 while(begin<end&&*end>=*k)29 {30 --end;31 }32 while(begin<end&&*begin<=*k)33 {34 ++begin;35 }36 swap(begin,end);37 }38 swap(begin,k);39 40 quickSort(p,end-1);41 quickSort(begin+1,q);42 }43 44 int main()45 {46 int a[]={4,3,1,0,2,8,6,7,5,9};47 int len=sizeof(a)/sizeof(a[0]);48 quickSort(a,a+len-1);49 printArray(a,len);50 51 return 0;52 }
六、指针操作字符串
1、字符串常量,存放在“字符串常量区”,字符串在C语言中,是按照字符数组的方式处理的。
2、说明
同一个字符串常量,在常量区,只会保留一份。
使用的字符串:
- 一种是存放在栈空间上的字符串 //char s[10]="hello"
- 一种是存在字符串常量区的字符串 //char*p="hello"(字符串常量区的数据不能被修改)
3、const本身表示只读 ,const修饰的原则,离谁近就是限定谁的。
const放在指针中,可以修饰两个部分
- 一个是基类型:const char *s和 char const *s
不能通过*s的方式修改基类型
- 一个是指针变量:char *const s
表示s是只读的,s的指向不能被修改
4、strncpy函数
char *strncpy(char *dest,const char *src,size_t)n<=strlen(src):将前n个字符拷贝过去
n>strlen(src):将src字符拷贝过去后,n如果还没到达0,这时候需要继续拷贝,剩余的次数后续拷贝全是0
5、
七、指针操作二维数组
1、二维数组定义
int(*p)[4]*表示定义的是一个指针类型变量
p表示是指针变量名,剩余的就是基类型
基类型是一个数组类型int[4]
此时这个指针变量叫做数组指针,因为指向的基类型为数组类型
2、二维数组访问
*(*(p+i)+j)//*(p+j) 第一维度访问完成,此时整体代表内部的一维数组int[4]这种数组类型的数组名
//*(*(p+i)+j 在第一维的基础上访问第二维度,+j获得了内部一维数组int[4]中具体元素的地址,在此基础上继续做*运算,获得最终的数组元素。


八、指针操作函数
1、函数名代表函数的入口地址
2、函数头中 int add(int a,int b)去掉函数名,剩下的就是函数类型
3、书写形式
int (*p)(int a,int b);
//就是一个指向int (int a,int b)这种函数的一个指针变量4、函数指针:本质是个指针,指向的是一个函数
add() //定义一个add函数
add(1,2); //正常调用函数int (*p)(int,int)=add; //声明一个名为 p 的函数指针p(1,2); //指针调用函数
函数的指针变量可以用来调用函数
在函数指针中*p中的*运算不起作用
函数指针主要是实现函数回调(callback)
5、qsort函数
#include<stdlib.h>
void qsort(void *base, //待排序的数组的首地址 size_t nmemb, //元素的个数size_t size, //单个元素的大小 int (*compar)(const void *, const void *) //比较的规则 );
int compare(const void *a,const void *b)
{const int *p=a;const int *q=b;return *p-*q;
}
//*a是空类型指针,如果想通过空类型指针访问具体数据可以这样做:const int *p=acompare函数就是回调函数,整个过程就是回调
6、存放函数指针的数组
int(*p[4])(int,int); //函数指针数组7、指针函数——本质是个函数,返回值类型为指针类型的函数
char *strcpy(char *dest, const char *src); //返回值为指针类型的函数 说明:指针函数,意味着返回值是个地址 这个地址,不能是局部变量的地址,可以是字符串常和堆区的地址
8、malloc函数(指针函数)
void * malloc(size_t size);功能:申请内存 //堆区 参数:size --- 表示申请的空间大小 单位字节 返回值:void * 成功 返回申请到的内存空间的首地址 失败 NULL 使用:
int *p=malloc(sizeof(int)*10);9、free函数
void free(void *ptr); //释放 功能:将堆区空间释放 //将之前在用的空间交还给操作系统,告诉操作系统,说这块空间不用了,可以回收参数:ptr //要求: 代表堆区上的一块空间 //free 用之前 一定有malloc已经申请使用过的 堆区空间free(p)释放空间后,一般就要p=NULL
10、void类型指针
void * //空类型指针 //万能指针
//void * p ; //指针变量 --- 可以接收任意类型的指针
注意:
void类型的指针
想要进行指针间接访问的 运算
必须将 void * 类型指针 转换为 具体类型(int,short,float,double)的指针
11、NULL是空指针
12、考点1:该代码输出“段错误”

考点2:
一个有10个指针的数组,该指针是指向一个整型数的
int *a[10]
一个指向有10个整型数数组的指针
int (*a)[10]
一个指向函数的指针,该函数有一个整型参数并返回一个整型数
int (*fun)(int)
一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
int(* a[10])int
13、 一级指针和二级指针
int a=10;
int *p=&a;
int **q=&p;九、main函数的参数
int main(int argc,const char *argv[]) @argc 表示 --- 命令行参数的个数(数组长度)
@argv 表示 --- 存放着命令行字符串的指针数组(数组名)

