指针与字符数组,字符串和二维数组

指针 + 一维字符型数组:

字符串的储存原理:

char a[20] = "hello";//上述式子表示将字符串装进了字符数组空间中
原理解释:首先编译器先开了一块栈上的内存空间,然后去访问字符串常量空间,
一个个将字符串常量空间里的对应字母的ascii值拿出来放到了开出来的栈的空间之中,
由此实现了用数组存储字符串常量的方式,并可借助字符数组更改数据。(字符串常量区只可读不可写)

两种初始化方法:

char s[] = "hello";//先定义了一个数组装字符串
char *p = s;//再将开在栈空间上字符数组的首地址给了指针s

通过指针访问字符串的另一种方式(访问字符串常量空间)
const char *p = "hello";//后方字符串是一个常量,赋值操作的效果是将字符串常量首地址空间给了指针p(前方加的const标志着指针内的数据只可读不可写)*p = 'a'运算是非法的

const关键词:

单词含义:只读
作用:将修饰对象的权限更改为只读。

修饰字符指针的三种形式:(修饰对象不同)

判断修饰对象的原则:
就近原则(const离谁近就修饰谁)

1.const char *s;//1,2两种形式作用等价(const离基类型近,所以限定基类型数据不可更改)
2.char const *s;//const在中间,离指针和基类型一样近,以修饰基类型为主

3.char * const s;//该形式修饰的是指针本身的数据,限定p为只可读,。(const离指针近限定指针S内所存地址不可修改)

可以从三种不同的角度来理解其不同的形式:
以下将从三种角度分析第一种形式:

const int *p

1.操作角度:
上述一二两种形式限定基类型,表示不可以通过间接访问(即*p = ‘a’)的方式修改所指向的数据。

2.从类型角度:

const int *p 与 int *p 所代表的是不同类型的指针

3.权限角度:

const int *p //只能读p所指向的整形数据 
 int *p //其能读也能写指针指向的数据

重要的注意事项:当带const的指针和不带const的指针涉及到地址赋值时;要注意所修饰指针的权限只可缩小不可扩大。

eg:
const int *p ;  
 int *p ;
 p = q;//把可读写的权限缩小到可写;是合法的形式
 q = p;//将只可读的权限阔刀到了可读可写,是不合法的形式。

应用:

应用:
1.如果 不想 通过*p方式改变基类型对应的数据

const int *p = &a;  
int const *p = &a;  

2.如果 指针变量p 定义好后,不想再指向别的变量则

int * const p = &a;

const 函数在函数调用参数的使用:

举例:
void Puts(char *ch)
char s[10];
如果此时主函数出现了错误代码:
Puts((*s)++);
则字符数组中的数据就被修改掉了。因此为了避免这种现象可以采用以下写法:
void Puts(const char *ch)
其表示传过来的指针限定了基类型,一旦出现修改指针所指向的数据就会发生报错。

使用注意:
形参 设计为 const char *
1.目的:
防止函数中的误操作

2.好处
(1).提前发现问题
将运行时问题,提前到编译时
(2).const char *
可以接收
char *
const char *

实参:
可以 数组名
可以 指针变量 char *p 或const char *p
可以 直接是一个字符串常量
提高参数的适用性

注意:
能写成const的 都写const

指针+字符串:

字符串在c语言中以字符数组的形式存储。
字符串常量——存储在字符串常量区

处理字符串:

指针指向字符串两种形式:
char s[] = "hello"; //表示 在栈上开辟一块空间,用字符串常量中的 "hello"
                 //进行初始化 
   
const char *p = "hello"; //表示 p指向了 字符串常量区中的 "hello"
                      //因为 是指向了字符串常量区 
	                 //只能做读取操作,不能修改

涉及新函数:

  char *Strncpy(char *dest, const char *src, size_t n)//限定长度复制函数
  char *Strncat(char *dest, const char *src, size_t n)//限定长度拼接函数
  int strncmp(const char *s1, const char *s2, size_t n);//限定长度比较函数

以上函数请自行了解更为详细的博客,此处只做简单提及。


指针 + 二维数组:

回顾二维数组的形式:

int a[2][3]
1.c语言中并不真正存在二维数组
2.二维数组的本质是一维数组的一维数组。
3.二维数组也符合数组的特点。
本质上可写为:
int[3] a[2]

指针如何表示二维数组的两个问题:

1.所要处理的数据是什么类型的?
由于是二维数组,所以其数据类型相当与是一个一维数组
因此可知指针的基类型为:

基类型:int [3] 

2.需要定义什么样的指针来表示数组:

确定了基类型,则只需按照类似指针定义方式定义指针就可以推出以下形式:
int [3] *a;//不标准写法,非法
但是c语言不支持这种写法不支持该种写法,所以换为

正确写法为:int*a)[3];//其就表示二维数组的指针 

结合初始化理解:
int b[3][4]
int (*a)[4] = b;//其表示定义了一个一维的指针变量并将二维数组b的首地址给了过去。(个人理解:a代表了整一个二维数组,int[4]就可以知道它每一行的偏移量,然后其a[0]偏移量一块是 int所代表的字节*4)

等价:
*p <=> a[0] // 相当于是内部这个一维数组的数组名,第一行地址(当做外层) 
       (*p)[0] //指的是第一行第一个位置,将下标运算符扩展,从第一行地址还要进入内层(精准偏移到所指位置)
       *(*p+0) //**p

由此可推出一般式子:
*(*(p+1)+1) <=> a[1][1]
*(*(p+i)+j) <=> a[i][j]

散装知识点:

void *memcpy(void *dest, const void *src, size_t n)
 {
      //一个字节一个字节拷贝 
 }
void * //NULL 空指针 
       //空类型的指针 --- 万能指针
   	//可以接收任意类型的指针
   	
注意:
 1.注意,如果用 空类型指针 进行 间接运算 
         必须 转换成 有明确类型的指针 
         ```
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值