博客
关于我
C语言指针收藏
阅读量:410 次
发布时间:2019-03-06

本文共 5477 字,大约阅读时间需要 18 分钟。

指针是什么

》》每一个内存单元只能同时存储一个数据,如何保证内存单元同时只能存储一个数据,可以使用编号的方式实现内存单元标记,此编号就是指针。

》》指针是一个变量,指针是存放着一个数据的内存地址而不是数据本身的值,其是查找数据的另一种方式

相关运算符

【&】在变量中取地址

【*】在地址中取变量

测试小程序:

#include
void main() { int i = 10;//定义一个变量,并赋初始值为10 int *p = &i;//定义一个指针变量,并赋初始值为i的地址 *p = 199; printf("%d=%d", *p,i);//输出199=199 printf("---%d---", p);//得到变量i的地址}

指针变量的类型

》》指针类型:int *、float*、long*、double*、char*等等

》》指针变量的类型需要与存储的数据类型相同

》》确定类型可以方便指针变量确定存储数据的大小,为数据寻找到结束符,如int类型占四个字节、char占一个字节。也方便指针使用加1或减1操作,如int加减1会跳动4个字节,char加减1会跳动两个字节。

指针的赋值

int i=10;  int *p=&i;

int *pp;

pp=p;

指针运算符:

*p++

等同于*(p++),运算优先级为从右到左,应该是先*p取值,然后地址移动一位,要区别与*(++p)。

char *ch="0123"; //printf("%c\r\n",*ch++);//输出0  //printf("%c\r\n",*(ch++));//输出0  printf("%c\r\n",*(++ch));//输出1

指针变量作为函数参数

#include
//int *a1=&b1;void fun(int *a1, int* a2) { *a1 = 100; int ii = 99; a2 = ⅈ//让指针重新指向另外一个地址 printf("得到的数据:%d,%d", *a1, *a2);//输出100,99}void main() { int b1 = 1, b2 = 2; fun(&b1, &b2); printf("调用函数后:%d,%d", b1, b2);//输出100,2}

输出b2的结果并不是相同的值,是因为执行调用函数改变了实参指针变量的值,并不是改变了实参指针变量所指变量的值

数组作为函数参数

#include
void fun1(int *arr){ arr[0]=10; arr[1]=11;}void fun2(int arr[]){ arr[2]=100; arr[3]=110;}void main(){ //变量初始化 int i; int a[]={0,1,2,3,4,5,6}; //函数调用 fun1(a); fun2(a); //打印 for(i=0;i

数组作为函数参数会自动退化为指针

函数形参如果是数组,不管下标是多少都会自动转换为数组的首地址指针

1 #include
2 3 void fun1(int *p){ 4 printf("%d",p[0]);//10 5 } 6 void fun2(int p[]){ 7 printf("%d",p[0]);//10 8 } 9 10 void fun3(int p[100]){11 printf("%d",p[0]);//1012 }13 14 void fun4(char *p[]){15 printf("%s",p[0]);//dong16 } 17 18 void fun5(char **p){19 printf("%s",p[0]);//dong20 } 21 22 void main(){23 int ii[]={10,11,12};24 fun1(ii);25 fun2(ii);26 fun3(ii);27 char *ch[]={"dong","xiao"};28 fun4(ch);29 fun5(ch);30 }

一维数组指针变量

数组名(如arr)代表元素的首地址,数组第一个元素的地址也是这个数组的首地址(如&arr[0])。

数组指针中使用加减1将跳到下一个或者上一个数组元素地址,与使用 &arr[n+1] 基本相同。

如果整数数组名为arr,运行int *p=arr,则*(p+3)、p[3]、*(arr+3)、arr[3]效果均是取出数组arr的第三个元素,在编译时arr[3]实际上是*(arr+3)处理的。

#include
void main() { int arr[] = { 5,4,3,2,0 }; int *p = arr; int *pp = &arr[0]; printf("%d", *(p+3));//输出2}

函数数组参数

#include
//等价于void fun(char a1[]) {void fun(char *a1) { *(a1 + 2) = 'c';//改变第二个值的内容}void main() { char b1[] = { "123456789" }; fun(b1); printf("调用函数后:%s", b1);//输出: 12c456789}

二维数组指针变量

#include
void main() { int a1[][3] = { {10,11,12},{100,110,120} }; int a[][3] = { 10,11,12,100,110,120 }; printf("地址:%d==%d==%d==%d", a[0], &a[0][0],*(a+0),a+0);//输出地址 printf("%d===%d==%d", a[0][1], *(*(a + 0)+1),*(a[0]+1));//得到值}

指针引用字符串

字符串常量【char *ch = "dong xiao dong";】表示其指向地址的内容不可变,但指向的地址是可变的;

字符串变量【char ch[] = "dong xiao dong";】其指向地址的内容可变。

#include
void main() { //char *ch = "dong xiao dong"; //字符串常量,不可变 char ch[] = "dong xiao dong"; //字符数组,可变 ch[2] = '2';//字符串常量运行这条将报错 printf("%s\n", ch);}

可变格式的输出函数:

#include
void main() { char *ch = "dong xiao %d\n"; printf(ch, 10); ch = "xiaoxiao%d\n"; printf(ch, 10); char chh[] = "dongdong %d\n"; printf(ch, 100);}

指向函数的指针

【int(*p)(int, int);//定义一个函数指针变量p】,第一个int表示返回值类型,第二个int和第三个int表示函数的参数类型。注意*p两侧的括号不能省略,表示p先与*结合,是指针变量,然后再于后面的()结合,()表示是函数,即该指针变量不是指向一般的变量,而是指向函数。如果写成“int * p(int,int);”,由于()优先级高于*,它相当于“int *(p(int,int))”,就成了声明一个p函数,并且这个函数的返回值是指向整型变量的指针。

返回值为int

#include
void main() { int minto(int a, int b);//函数声明 int(*p)(int, int);//定义一个函数指针变量p p = minto;//函数指针指向函数minto首地址 int cc = (*p)(11, 55);//调用函数 printf("Min===%d", cc);}int minto(int a, int b) { if(a > b) return b; else return a;}

无返回值:

#include
void main() { void fun(int a);//函数声明 void (*p)(int);//定义一个函数指针变量p p = fun;//函数指针指向函数fun首地址 (*p)(11);//调用函数}void fun(int a) { printf("%d\n", a); }

指向函数指针作为函数的参数

#include
void main() { int fun(int(*addpp)(int, int), int x, int y);//函数声明 int add(int i, int j); int ii=fun(add, 11, 12);//传递函数名和参数即可 printf("输出相加的值为:%d", ii); }//int (*addpp)(int,int);addpp=add;int fun(int (*addpp)(int,int),int x,int y){ int cc = (*addpp)(x, y); return cc;}int add(int i, int j) { return i + j;}

返回指针的函数

#include
void main() { int* add(int i, int j); int *p = add(10, 4); printf("输出相加的值为:%d", *p); }int* add(int i, int j) { int aa = i + j; return &aa;//返回地址}

指针数组

一个数组其全部元素都存放着指针,就是指针数组【int * p[5];】

#include
void main() { //指针数组 char * p[] = { "dong1","xiao2","dong3","dong4" }; printf("%s\n", p[2]); }

进阶版

#include
void main() { //指针数组(字符串) char * p[] = { "dong1","xiao2","dong3","dong4" }; char **pp; pp = p; printf("%s\n", *(pp+1));//转换一次就可以拿到对应字符串的首地址通过%s打印 //指针数组(整数) int a[5]= {10,11,12,13 }; int * ip[] = { &a[0],&a[1],&a[2],&a[3],&a[4]}; int **ppp = ip; printf("%d\n", *(*ppp+1));//转换第一次得到存储的指针,再次转换得到值 }

void类型指针

void a;//定义一个无类型变量,错误,不能确定分配的内存大小void *a;//定义一个无类型指针,可行,指针类型都是4个字节(32位,64位为8个字节)

void *p;表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。

可以将任意类型的指针直接给void指针赋值,但是如果需要将void指针的赋值给其他类型的指针,则需要进行强制类型转换

#include
void fun1(void *i){ int *p=(int *)i;//强制类型转换 *p=100;}void main(){ int ii=10; fun1(&ii); printf("%d",ii);//输出100 }

错误示范

1、

int *p=10; //等同于:int *p; p=10;

分析:非法操作,内存地址不能用户自定义。10相当于一个内存地址,该内存地址的值不确定且也不明确该地址是否可以直接访问,正确的应该是使用【&变量名】得到内存地址。

 

2、

int f = 12.3;int *p;*p = &f;  //错误1int ff = &f; //错误2

分析:指针(地址)必须赋值给指针变量

转载地址:http://fbfuz.baihongyu.com/

你可能感兴趣的文章
记2020年初对SimpleGUI源码的阅读成果
查看>>
C语言实现面向对象方法学的GLib、GObject-初体验
查看>>
系统编程-进程-ps命令、进程调度、优先级翻转、进程状态
查看>>
为什么我觉得需要熟悉vim使用,难道仅仅是为了耍酷?
查看>>
一个支持高网络吞吐量、基于机器性能评分的TCP负载均衡器gobalan
查看>>
HDOJ2017_字符串统计
查看>>
高等软工第二次作业《需求分析阶段总结》
查看>>
404 Note Found 团队会议纪要
查看>>
CentOS安装Docker-ce并配置国内镜像
查看>>
使用JWT作为Spring Security OAuth2的token存储
查看>>
使用Redis作为Spring Security OAuth2的token存储
查看>>
【SOLVED】Linux使用sudo到出现输入密码提示延迟时间长
查看>>
springmvc转springboot过程中访问jsp报Whitelabel Error Page错误
查看>>
项目引入非配置的文件,打成war包后测试报错的可能原因
查看>>
Git学习笔记
查看>>
SpringBoot笔记
查看>>
让你的代码更优秀的 14 条建议
查看>>
不需要爬虫也能轻松获取 unsplash 上的图片
查看>>
痞子衡嵌入式:语音处理工具pzh-speech诞生记(2)- 界面构建(wxFormBuilder3.8.0)
查看>>
将博客搬至CSDN
查看>>