C 指针,数组,字符串

指针:

 

1.指针定义与使用

 

sizeof(p)不管是指向什么类型的指针,它的sizeof(p)都是4,即4个字节(32位的地址)

 

int *p

char *p

float *p

struct NODE *p

 

 

*p+1 取值,值加一

++(*p) 取值,值加一

(*p)++ 取值,值加一

++*p 取值,值加一

++(*p)取值,值加一

 

*p++ 取值,指针加一

 

*++p 指针先加一,取值

 

*(p+1) 指针先加一,取值

 

 

指针与空值比较:

if(p==NULL)

对于返回指针的函数返回值一定要用if(p==NULL)做判断,否则很有可能p指向一个未知的危险地址

if(p) 危险(未初始化、初始化、释放后)if(p)条件都为真

指针变量未赋值时,可以是任意值,是不能使用的,会造成意外错误。而指针变量给NULL值后,则是可以使用的,只是不指向具体的变量。

 

定义一个指针时,最好初始化p=NULL;

 

 

2.指针运算

int *p,*q;

p++

p--

p+1

p-1

p-q;

p>q;

 

以当前定义为例:

规则:1.指针做加1或者减1运算代表指向下一个int类型的数据或者前一个int类型的数据,指针指向的位置是当前地址加上sizeof(int),或者当前地址减去sizeof(int)

2.指针之间可以做减法运算,前提是两个指针类型一致,指向同一数据元素(比如指向同一数组)

减法的含义代表两个指针之间元素的个数;

3.指向同一数据元素(比如指向同一数组)指针可以比较大小,p>q;

 

3.指针与数组(一维数组、二维数组)

int a[10];

int *p=a;

*(a+i), a[i], *(p+i), p[i]

 

字符数组的值:

1.定义的同时初始化

2.输入函数scanf\gets\fgets

3.字符串函数strcpy

 

char a[]="hello world";

char *p=a;

p="today"; 对 把内存中“today”字符串常量的地址赋值给了p

a="today" 错

 

结论:指针是地址变量,而数组名是地址常量,数组名在运算中可以作为指针参与,但不允许被赋值,指针可变,允许指向别的位置

 

指针和数组常见等价操作:

指针操作 数组操作 说明

p &a[0] 数组首地址

*p a[0] 数组的第一个元素

p+i &a[i] 数组的第i个元素的地址

*(p+i) a[i] 数组的第i个元素

*p+b a[0]+b 数组的第一个元素的值加b

*(p+i)+b a[i]+b 数组的第i个元素的值加b

 

注:当前p指向第i个元素

*p++ a[i++] 先取得数组的第i个元素的值,i加1//先取得数组的第i个元素的值 指针p再加一,指向a[i+1]

*++p a[++i] 先i加1,取得数组的第i+1个元素的值,//指针p先加一,指向

a[i+1],再取得数组的第i+1个元素的值

*p-- a[i--] 先取得数组的第i个元素的值,i减1//先取得数组的第i个元素的值 指针p再减一,指向a[i-1]

*--p a[--i] 先i减1,取得数组的第i-1个元素的值,//指针p先减一,指向

a[i-1],再取得数组的第i-1个元素的值

二维数组:

行指针、列指针

&a[0][0] == a 值一样,含义不一样

&a[0][0]表示数组首地址,列地址

a表示数组首地址,行地址

地址和值:

&a[i][j] &a[i][0]+j a[i]+j *(a+i)+j

a[i][j] *(&a[i][0]+j) *(a[i]+j) *(*(a+i)+j)

 

 

4.多级指针(指针的指针)

int **p;

原理见截图

理论上多级指针最多可以到12级别,实际上2级指针用的加多

 

5.指针数组

int *p[10];

char *a[20];

p是一个指针数组,数组的名字是p,数组有10个元素,每一个元素值都是一个指向整形数据的指针

 

注意事项: int (*p)[10]的区别,这是一个指针,指针的名字是p,指向一个含有10个元素的整形数组

int a[10];

int (*p)[10];

p=a;

 

指针数组的引用可以认为是一个指向指针的指针,因为数组名本身代表地址,可以做指针参与运算(不能改变其值)数组元素的值是指针,,因此是二级指针,**p

 

6.字符串、字符指针数组

 

C语言本身没有字符串类型,用字符数组来表示字符串(约定最后一个字符是'\0');

 

char *s="Welcome";

 

初始化字符串指针时,实际是把内存中字符串的首地址赋值给指针变量,并不是复制字符串给指针,因为指针只占4个字节,用来保存一个地址

 

 

字符数组与字符串函数

#include <strings.h>

strcasecmp, strcat, strchr, strcmp, strcpy, strdup, strlen,

strncat, strncmp, strncpy, strncasecmp, strstr, strtok

 

#include <stdlib.h>

atoi, atol, atoll, atoq - convert a string to an integer

strtod, strtof, strtold - convert ASCII string to floating-point number

 

字符型指针数组实现程序主菜单!!!!

 

7.指针函数

指针函数:若一个函数返回的是指针,则称该函数为指针函数。

 

函数内部的变量都是局部变量,当函数执行完后,会自动释放,在主调函数中不能再访问,访问一段释放的内存,是非法操作,若修改非法内存中的值,可能会出现严重后果,不可预料。

 

解决方法:

1. 用static将局部变量变为静态局部变量

2. 字符串常量类似于静态变量,在程序结束时,才释放内存。函数中使用 char *str="Welcome"; "Welcome"是一个常量,在内存中有确定的地址,把这个地址返回给主调函数是可以的

3. 在堆空间分配内存,返回分配内存的地址给主调函数。str=(char *)malloc(20);

注意:堆空间的使用一定要注意使用后要释放。 malloc / free 一定是对应的,如果不释放,指针已经指向其他地方,此空间成为内存泄漏空间。

8.函数指针

函数指针是一个专门用于保存函数首地址的指针,实际上就是函数的入口地址。

函数指针指向哪个函数,(*P)()就调用哪个函数。

 

int (*p)();

实例分析:call.c

输入字符串a+b 调用strsplit函数根据运算符+分割字符串,分割后保存在指针数组char *pstr[]; pstr[0]保存的是第一个操作数a的地址(此时仍当作字符串处理))pstr[1]保存的是第二个操作数b的地址(此时仍当作字符串处理)),使用atoi函数将字符串转换成整形数据,将q指向要调用的函数,调用operate(q,a,b),就完成了相应的运算。

 

int(*p[10])() 函数指针数组

 

 

9.const与指针

 

const int *p;

int * const p;

区别:把数据类型去掉const int *p->const *p 说明*p是常量,即p指针指向的内存空间的整形值不允许更改

把数据类型去掉int * const p-> * const p 说明指针p是常量,即p指针不能改变;

3 int a=10,b=20;

4 const int *p;

5 int * const q=&b;

6 p=&a;

7 //*p=30;//非法

8 p=&b;

9 //q=&a;//非法

10 *q=30;

 

 

10.void指针

void*

void指针不是空指针,而是一种不确定数据类型的指针,可以通过强制类型转换将void型指针转换为任何类型的指针。

举例:

void *malloc(size_t size);

 

char a[20]

a=(char *)malloc(sizeof(a));

 

int b[20]

b=(int *)malloc(sizeof(b));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值