指针的深入研究 ---- 指针进阶

 

 

 

 

 

目录

一、指针与数组

1.1、指针与数组

1.2、指针与字符串

​1.3、数组名作为指针

二、指针与多维数组

三、指针与数组参数

第一种情况:实参是数组,形参也是数组

第二种情况:实参是数组,形参是数组指针

第三种情况:实参是数组指针,形参是数组指针

第四种情况:实参是数组指针,形参是数组

例题:输出字符串“abcdefgabcdeabc”,这26个字母中小写字母出现的次数

三、指针与字符串

3.1、使用指针创建字符串

3.2、使用指针处理字符串

3.2.1、字符串复制

3.2.2、字符串连接

3.2.3、删除字符串中的#符号

3.3、指针的指针

3.4、指针数组与数组指针

3.4.1、指针数组

3.4.2、数组指针(行指针)

四、案例


一、指针与数组

1.1、指针与数组

指针用于存储地址,它和数组名紧密地联系在一起。

1.2、指针与字符串

  • 上图为一个grade的数组,里面有5个元素,每个元素占4个字节
  • 访问数组元素,可以使用下标来实现。
  • 上面数组已知grade[0]的地址,可以通过增减偏移量,得到grade[3]的地址,从而访问到grade[3]的元素值。

 

表达式"&grade[3]=&grade[0]+3*4"的含义是gradep[3]的地址等于grade[0]的地址加上12

数组中的下标为N元素的地址= 数组的首地址+N*sizeof(DataType)

  • int grade[5];    // 定义grade 为包含5个整数数据的数组
  • int *p;             // 定义p为指向整型变量的指针变量
  • p=&grade[0];

1.3、数组名作为指针

    对于每个创建的数组,数组名就成为编译器为这个数组所创建的指针常量名称,存储的是数组第1个元素的起始地址,也就是数组的首地址。因此就多了一种获取数组元素的手段,如:p=&grade[0]; 可以写成  p=grade。

p是指针变量,它的初始值是grade数组的首地址

 

 

 

#include "stdio.h"
int main(void)
{
 int array[10];
 int i,j,n,m,arrayend;
 int *p;
 printf("输入共有多少个数字:\n");
 scanf("%d",&n);
 printf("需要后移多少位:");
 scanf("%d",&m);
 printf("请依次输入%d个数:\n",n);
 for(i=0;i<n;i++)                  // 输入数据
	  scanf("%d",&array[i]);
 for(i=0;i<m;i++)
 {
    arrayend=*(array+n-1);         // 保存指针
	p=array+n-1;                   // 指针赋值
	for(j=n-1;j>0;j--)             // 循环移动
	{
	*p=*(p-1);
	p--;
	}
	*p=arrayend;  // 回复指针

 }
 printf("输出移动后的%d个数:\n",n);
 for(i=0;i<n;i++)
	 printf("%d",array[i]);
 printf("\n");
 return 0;
}

 

二、指针与多维数组

二维数组array[2][3](这6个数据在内存中按照z型排列),在内存中的存储形式

多维数组的数组名也被编译创建为常量,用来存储该数组的首地址

数组名array存储的是array[0][0]元素地址,存储的值位&array[0][0]

多维数组和指针的关联:首地址加偏移量,可使指针指向该数组中任何一个元素

三、指针与数组参数

第一种情况:实参是数组,形参也是数组

主调函数:int arr[10]; function(arr);   // arr实参

被调函数:function(int arr[]){}           // arr[]形参

第二种情况:实参是数组,形参是数组指针

主调函数:int arr[10];function(arr);    // arr 实参

被调函数:function(int *p){}              // p形参

第三种情况:实参是数组指针,形参是数组指针

主调函数:int arr[10];    int *p=arr;  function(p);   // 实参 p

被调函数:function(int *q){}                                   //形参q

第四种情况:实参是数组指针,形参是数组

主调函数:int arr[10];  int *p=arr;   function(p);  // 实参   p

被调函数:function(int arr[]){}                             //  形参   arr[]

例题:输出字符串“abcdefgabcdeabc”,这26个字母中小写字母出现的次数

实参是数组,形参是指针+数组

三、指针与字符串

3.1、使用指针创建字符串

定义message1[10];为10个字符串声明存储空间,并自动地创建一个包含指针的常量message1,存储的是message1[0]的地址。与常量一样指针常量指向是明确的,不能被修改。

使用指针创建字符串

char *message2="hello world!"

char message1= "hello world!"  此种形式的定义,有固定的数组存储空间,该数组一旦被初始化就不可再修改。

如:char message1 = "are you ok?"  修改成这样,显然是错误的。


#include "stdio.h"

int main(void)
{
  char *p,s[6];  // 定义一个字符型的指针与数组
  int n;         // 定义变量
  n=0;           // 初始化变量
  p=s;           // 指针p指向数组s,本质是指向数组s[0]的首地址
  printf("输入你要转换的八进制:\n");  // 输出函数 同printf
  gets(p);   // 输入函数  同scanf
  while(*(p)!='\0')      // 检测指针是否都是以字符串数组结尾
  {
  n=n*8+*p-'0';          // 八进制转化为十进制的公式
  p++;                   // 指针后移
  }
  printf("转换的十进制是:\n%d\n",n);
  return 0;
  return system("pause")
}

 

3.2、使用指针处理字符串

3.2.1、字符串复制

3.2.2、字符串连接

3.2.3、删除字符串中的#符号

注意事项:

  • 保留当前地址,代码中p=arr,t=p,这样写的目的是用于恢复到当前位置
  • 指针连续出现“#”的解决办法,采用先向前移动,然后重新检查该位置字符,p--
  • strarrange函数返回的arr指针,该指针始终指向s字符串的首地址

 

3.3、指针的指针

  • 指针可以字符串
  • 指针的指针可以指向一组字符串

 

 

3.4、指针数组与数组指针

3.4.1、指针数组

  • 数组由指针类型的元素组成 (存储相同类型指针的数组)     int *p[10]  该数组p由10个指向整型元素的指针组成
  • ()优先级高 
  • p+1是错误的执行 p=b也是错误的执行 因为不知道p表示的是什么 
  • 但可以执行*p=&b  因为*p表示数组的(p[0]的地址)的首地址,b首地址的值
  • p[0]是一个指针变量
  • 指针数组用法同指针一样,这些指针的名字相同(都是p),靠下标区分 

 

3.4.2、数组指针(行指针)

  • int (*p)[10]
  • []优先级高
  • p是一个整型指针指向一个数组元素为10的数组
  • p+1的执行要跨过10个整型数据的长度

二维数组的赋值方式   

 

 

四、案例

#include <stdio.h>
/*有个人围成一圈,顺序排号,从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的哪位是原来的第几号*/
#define nmax 50
int main(void) {
    int i,k,m,n,num[nmax],*p;
    printf("请输入总人数:\n");

    scanf("%d",&n);
    p = num;
    for(i=0; i<n; i++)
        *(p+i)=i+1;
    i=0;
    k=0;
    m=0;
    while(m<n-1) {
        if(*(p+i)!=0)

                k++;
        if(k==3) {
            *(p+i)=0;
                k=0;
                m++;
            }
        i++;
        if(i==n)
        i=0;
    }
while(*p==0)
        p++;
    printf("%d号留下来了",*p);
    return 0;
    return system("puase");
}


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭日初扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值