学习指针第三日

const

const //只读  

const int a; //a 此时是一个只读的变量

1.四种用法

   int a = 10;
  //int *p = &a;

  const int *p = &a;   //const限定是 基类型 
    //表示不能通过 *p 的方式 修改基类型数据                      
  int const *p = &a;   //const限定是 基类型 
    //表示不能通过 *p 的方式 修改基类型数据 
  int * const p = &a; //const限定是 指针变量p 
    //表示将p限定位只读 
    //表示p不能被修改 

  const int * const p = &a;  //基类型和指针变量 都被限定为只读
    // p = &b; //不能修改 
    //*p = b;  //不能修改 

应用:
    1.如果 不想 通过*p方式改变基类型对应的数据 
      const int *p = &a;  
      int const *p = &a;  
    2.如果 指针变量p 定义好后,不想再指向别的变量 
      则 
        int * const p = &a;

原则:
   就近原则  //const 离谁近 就限定谁

2.void Puts(const char *s)中使用const

注意:
  1.形参 设计为 const char *
    目的,
        防止函数中的误操作 
  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"
                            //因为 是指向了字符串常量区 
                            //只能做读取操作,不能修改

 

memcpy函数

void *memcpy(void *dest, const void *src, size_t n)
 {
      //一个字节一个字节拷贝 
 }
 void * 
        //空类型的指针 --- 万能指针
        //可以接收任意类型的指针
注意:
  1.注意,如果用 空类型指针 进行 间接运算 
          必须 转换成 有明确类型的指针 
 



void Memcpy(void *dest,const void *src,size_t n)  //n传的是字节数
{
	char *p = dest;
	const char *q = src;
	while (n)
	{
		*p = *q;
		p++;
		q++;
		--n;
	}
}

char *Strncpy(char *dest, const char *src, size_t n)
    {
        //1.始终拷贝了n下 
        
        //1. 拷贝 
            '\0' && n 
        //2. 考虑n 
             n有没有结束 
             完成剩余的次数的拷贝 
             拷贝过去的数据 '\0'
    }
 

char * Strncpy(char *dest,const char *src,size_t n)
{
	char *ret = dest;

	while ( n!=0 &&*src != '\0')
	{
		*dest = *src;
		++dest;
		++src;
		--n;
	}

	while(n)
	{
		*dest = '\0';
		++dest;
		--n;
	}

	return ret;
}

char *Strncat(char *dest, const char *src, size_t n)
{
   //1.可以指定 n 
   //如果 src 长度 > n  
    就将前n个字符拼接过去 
   //如果 src 长度 < n
    直接将src字符串拼接过去
    
   最终 一定要保证 dest是一个字符串 '\0'

}
 

char * Strcat(char *dest,const char *src)
{
	char *ret = dest;

	while (*dest != '\0')
		++dest;

	while (*src != '\0')
	{
		*dest = *src;
		++dest;
		++src;
	}

	*dest = '\0';

	return ret;
}

char * Strncat(char *dest,const char *src,int n)
{
	char *ret = dest;

	while (*dest != '\0')
		++dest;

	while ( n && *src != '\0')
	{
		*dest = *src;
		++dest;
		++src;
		--n;
	}

	*dest = '\0';

	return ret;
}

int strncmp(const char *s1, const char *s2, size_t n);
    //表示值比较 s1 和 s2 中前n个字符 
    {
       多了一个比较限制条件 n 
    }
    

int Strcmp(const char *s1,const char *s2)
{
	while (*s1==*s2 && *s1!='\0' && *s2!='\0')
	{
		++s1;
		++s2;
	}

	return *s1 - *s2;
}

int Strncmp(const char *s1,const char *s2,size_t n)
{
	//n = 3 s1 s2 
	//n = 2 s1+1 s2+1
	//n = 1 s1+2 s2+2 
	//      s1+3 s2+3 //n = 0 
	while ( n > 1&&*s1==*s2 && *s1!='\0' && *s2!='\0')
	{
		++s1;
		++s2;
		--n;
	}

	return *s1 - *s2;
}

指针 操作 二维数组 

int a[2][3];

//二维数组 
1.c语言中并不存在,真正的二维数组。
2.二维数组本质 是一维数组的一维数组 
3.二维数组 也 符合数组的特点 //连续性,有序性,单一性 

//从二维数组的本质出发 
int[3] a[2]; 

问题:
1.确定需要定义什么类型的指针?
   &a[0]
    //a[0]  --- int[3]
    //&a[0] --- int[3] * 
    //c语言中 不支持 int[3] *  
    //正确写法 int(*)[3]

int(*p)[3] = a; //p指向二维数组 a 
                //p的基类型 int[3]

*p <=> a[0] // 相当于是内部这个一维数组的数组名 
       (*p)[0] 
       *(*p+0) //**p

*(*(p+1)+1) <=> a[1][1]
*(*(p+i)+j) <=> a[i][j]

注意:  
   二维数组的操作
   从二维数组的本质 进行的 
   二维数组的本质 一维数组的 一维数组
   直接的访问操作 也是 一维一维的展开  
 

#include <stdio.h>

int main(void)
{

	int a[2][3] = {1,2,3,4,5,6};

	int (*p)[3] = a;
	int i = 0;
	int j = 0;
	for (i = 0;i < 2; ++i)
	{
		for (j = 0; j < 3; ++j)
		{
			printf("%d ",*(*(p+i) + j));
		}
		putchar('\n');
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值