指针详解(二)——字符指针、指针数组、数组指针

目录

字符指针

指针数组

指针数组如何分辨数组中元素类型:

数组指针

如何正确写出能指向数组的指针 

注意如何分辨是指针数组还是数组指针: 

 数组指针的使用

数组名和&数组名


通过指针详解(一)我们已经了解到:

  1. 指针变量存储的是地址,每个地址唯一标识一个内存空间
  2. 指针的大小为4/8个字节
  3. 指针是有不同类型的,类型决定了指针+-整数的步长以及指针解引用所访问的字节大小
  4. 指针的运算
  5. 二级指针的指向是一级指针的地址

现在开始新的知识归纳 

字符指针

指针类型有char*类型,这种类型就叫做字符指针

字符指针的一般使用方法:

#include<stdio.h>
int main()
{
    char m="c";
    char *p=&m;
    
    return 0;
}

这里就是将字符变量m的地址赋予指针变量p;

字符指针的另一种使用方法:

#include<stdio.h>
int main()
{
    char m="csdn";
    char *p=&m;
        
    printf("%s",m);
    printf("%c",*p);//这里打印的是“c”
    printf("%s",p);//这里打印的才是“csdn”

    return 0;
}

 这里字符串的地址就是字符串首元素的地址,即c的地址,所以对指针p解引用并以字符的形式打印时,这里只能打印出首元素c;而指针变量p的值其实就是字符串首元素的地址,我们知道要打印一串字符串,只要给出字符串的首地址即可,所以我们只要提供指针变量p然后通过字符串的形式打印即可打印出csdn;

 注意:这里的csdn其实就是一个常量字符串

给出一道题目以便我们分清楚字符串、字符串数组和字符指针

#include<stdio.h>
int main()
{
    char str1="best csdn";
    char str2="best csdn";

    char str3[] = "hello csdn.";
    char str4[] = "hello csdn.";

    char*p1="hello csdn";
    char*p2="hello csdn";
    
    if(str1==str2)
        printf("&str1=&str2\n");
    else
        printf("&str1!=&str2\n");//结果是&str1=&str2

    if (str3 == str4)
        printf("str1 and str2 are same\n");
    else
        printf("str1 and str2 are not same\n");//结果是str1 and str2 are not same

    if(p1==p2)
        printf("p1=p2");
    else
        printf("p1!=p2");//结果是p1=p2

return 0;
}
    

可以看到用一个字符串去赋给两个不同的变量,两个变量的地址是相同的,因为两个变量的地址都是首元素b的地址; 

而给两个字符串数组赋予同一个字符串时,两个数组的首地址并不相同,因为两个数组分别开辟了两个内存空间,里面的字符串虽然相同,但是所处的内存空间是不同的;

而两个指针变量都是指向同一个字符串的首元素地址,所以它们的值是相同的。 

指针数组

指针数组,本质上还是数组,只不过数组里面存放的都是指针

int* arr[5];

arr里面5个元素类型都是int* 

以此类推

int**arr1[10];

arr1里面10个元素都是二级指针

指针数组如何分辨数组中元素类型:
  1. 我们要知道[]的优先级比*高
  2. 除去数组的变量名,剩下的就是变量类型

比如:

int arr[10] = { 0 };//除去变量名arr,变量类型为int [10]
int arr[3][4] = { 0 };//除去变量名arr,变量类型为int [3][4]
int* arr[10] = { 0 };//除去变量名arr,变量类型为int* [10]

 数组的变量类型决定数组的元素个数以及每个元素的类型

数组指针

我们已经了解了有指向整型的指针和有指向字符的指针,同时指针也可以指向数组;

数组指针,主语是指针,是指向数组的指针。

#include<stdio.h>
int main()
{
    int a=1;
    char b=0;
    char arr[10]={0};

    int *p1=&a;
    char *p2=&b;
    char *p3=&arr;

    return 0;
}

和基础的指针定义一样,我们只需要将数组的地址赋给指针变量即可。

如何正确写出能指向数组的指针 

我们要知道一个指针变量除去变量名和一个符号*,剩下的就是该指针所指向的类型

比如:

int a=10;
int *p1=&a;//指针p1去掉变量名p1和一个*,剩下的int就是p1指向的类型
char b=0;
char*p2=&b;//指针p2去掉变量名p1和一个*,剩下的int就是p1指向的类型

数组指针也是如此:  

#include<stdio.h>
int main()
{
    int *arr[10]={0};
    int (*p)[10]=&arr;
    
    return 0;
}

首先p是一个指针,因为用()将*和p结合,防止[]的优先级比*高而导致p与[]先结合

指针p指向的内容,即数组类型是int [10],所以数组指针p就变成了int(*p)[10]。
去掉变量名p和*后,便是该数组指针所指向的数组的变量类型,即为int [10]。

注意如何分辨是指针数组还是数组指针: 

 因为[]的优先级比*高,而()的优先级又比[]高,所以如果变量名与*没有用()括起来,并且变量名与[]相接触的就是指针数组。

而如果加上()后*与p结合则为数组指针

 数组指针的使用

 此处用一个打印二维数组的案例来分析数组指针应该如何使用

#include<stdio.h>
void print(int(*p)[5],int x,int y)
{
    int i=0;
    for(i=0;i<x;i++)
    {
        int j=0;
        for(j=0;j<y;j++)
        {
            printf("%d",*(*(p+i)+j));
        }
        printf("\n"};
    }
}
int main()
{
    int arr[4][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20}};
    print(arr,4,5);
    return 0;
}

这里打印一个4行5列的二维数组,主函数中arr传参传的是数组的首元素地址,也是一维数组的首元素地址,要接收一个数组的地址,这里就要是要数组指针*p来接收,用x,y明确打印的范围

解析*(*(p+1)+1)

数组名和&数组名

数组名代表整个数组的地址的情况其实只有两种:

  1. &数组名。
  2. 数组名单独放在sizeof内部,即sizeof(数组名)。

除此之外,所有的数组名都是数组首元素地址。

比如

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

只有以下两种情况才代表整个地址:

&arr;
sizeof(arr);

 除此之外都是首元素的地址,即1的地址。

打印出arr即首元素的地址与&arr虽然值是一样的,但是两者的类型不同;

&arr的类型是数组指针类型

而我们在指针详解(一)中讲过指针类型决定了它+-整数所走的步长

当arr+1后地址增加了四个字节,因为arr的类型是int,int类型所占的字节便为4

&arr[0]的情况和arr是一样的,&arr[0]就是arr中的第一个元素,是int类型,+1也是加4个字节;

而&arr就不同了,地址14到3C差了0x28总共40个字节(这里是按十六进制计算的),这里+1跳过了整个数组,而不是跳过一个元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LLhaibao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值