[c语言]小白入门理解c语言指针

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言:

在这里我们要先了解sizeof和strlen的作用

再通过他们来理解数组名,取地址数组名,和指向数组里面元素的指针,和取地址数组元素等的意义


一、sizeof和strlen的用法

sizeof是操作符,strlen是包含再string.h里面的库函数

  1. sizeof()用于计算类型所占空间大小,他不会计算()内的值,仅仅是计算所占空间大小而已。举个例子:
    int main()
    {
        short s = 5;
        printf("%d\n", sizeof(s = 1 + 1));
        printf("%d\n", s);
        return 0;
    }

    这个计算出来第一个是2,第二个是5一个表达式有两个属性,一个叫值属性,一个叫类型属性,而sizeof计算的就是类型属性

  2. int main()
    {
        int arr[3] = {0};
        printf("%d\n", sizeof(arr[4]));
    
        return 0;
    }

    知道是计算类型属性的话,即使数组越界了也是能够正常作用的。这里计算出来结果就是4,一个int型。

        2. size_t strlen(const char* str);这是strlen的定义,由定义可以知道,我们传入一个指针,得到一个整形,它的计算该整数是从该指针指向的元素开始开始,一直++,直到遇到'\0'停止.      例子:

int main()
{
    char a[] = { 'a','b','c' };
    char b[] = { 'a','b','c','\0' };

    printf("%d\n", strlen(a));
    printf("%d\n", strlen(b));
    return 0;
}


二、了解指针

1.利用整形数组来了解指针

代码如下(示例):

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

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));

注:除了sizeof(数组名)和&数组名,取出的是整个数组地址外,其余的都是首元素

(以下答案以vs2022,x86环境参考)

一张图知道符号指代什么:虽然地址值一样,但是意义却不一样,接下来我们来找出这些意义的不同

1.第一个,sizeof计算数组类型的大小,整个数组大小为4*4=16

2.第二个,a是指向数组首元素的指针,+0之后还是代表指向首元素的指针,注意区分a,它此时不是数组名了,只是一个指针,所以这里计算的是地址的大小了,结果为4

3.第三个,a是指向数组首元素的指针,解引用后就是数组首元素,因为首元素类型是int型,这里计算的是元素类型大小,所以这里计算出来的是4

4.第四个,a是指向数组首元素的指针,a的类型是int*,所以+1向后跳过一个int型,a+1就变成了指向数组第二个元素的指针,这里计算的是指针的大小,所以这里计算出来的是4

5.第五个,a[1]就是数组第二个元素,这里计算的是元素类型大小,所以这里计算出来的是4

vs截图:

    printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));

先理解a和&a有什么区别呢?

1. 先看各自地址:

可以看到地址是一样的,都是取的首元素的地址。

2.再看访问权限:

可以看到,a + 1跳过一个int型,而&a + 1跳过4*4个int型,即跳过了一个数组,由此可以知道&a取的是一个数组的地址,它的类型就是int (*)[4],一个数组指针。 

知道了这两点后再看题:

    printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));

 1.第一个,sizeof计算的是一个数组指针的大小,所以结果为一个指针的大小,即4

 2.第二个,&a取的是一个数组的指针int (*)[4],所以解引用后就变成了int [4],即一个数组类型,所以结果是4*4=16

 3.第三个,&a + 1即向后跳一个数组,这时候它指向为:

    

 它的类型仍然是int (*)[4],所以结果仍然是一个指针大小,即4

 4.第四个,a[0]代表第一个元素,&它即为指向第一个元素的指针,结果为4

 5.第五个,指向第一个元素的指针加1,所以指向第二个元素,如图:

它的类型是一个整形指针,所以结果为4


2.利用字符数组来了解指针

代码如下(示例):

char arr[6] = { 'a','b','c','d','e','f' };
    printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

strlen只管接收地址,然后从该地址出发寻找'\0'

一张图理解指代什么:

1.第一个,arr代表首元素地址,所以从首元素地址出发,寻找,结果为随机值

2.第二个,arr + 0也是代表首元素地址,所以结果也是随机值

3.第三个,arr代表首元素地址,解引用就找到了首元素'a',实参传入的会是a的ASCII值,97,即0x00000061,强制将其转换成地址并且访问,然后出错

 4.第四个,与第三个一样,arr[1]代表第二个元素,出错

 5.第五个,&arr代表取该数组的地址,类型为char (*)[6],但是该地址的数据和首元素地址一样,所以传参时发生类型转换,数据不转换,所以它的意思是,从首元素出发寻找,结果为随机值

 6.第六个,&arr代表数组地址,加一后跳过一个数组,如下图:

 所以,它的结果为随机值-6

 7.第七个,arr[0]代表第一个元素,&它即为指向第一个元素的指针,加一后指向第二个元素,如下图:

 所以,它的结果为随机值-1

vs截图:


3.利用字符指针来理解指针

 代码如下(示例):

    char* p = "abcdef";
	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p+1));
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));
    printf("%d\n", sizeof(p));
    printf("%d\n", sizeof(&p));

先以一张图来了解整个题目符号都指代什么:

 1.第一个,p是一个指向常量字符串首字符’a'的指针从a出发寻找'\0',所以结果为6

 2.第二个,p + 1的意思就会是字符指针向后移动一个单位,这时指向了”b’,从b出发寻找'\0’,所以结果是5

 3.第三个,*p即寻找到了字符'a',这时是会发生访问冲突

 4.第四个,p[0]也代表了首元素,发生访问冲突

 5.第五个,p是指向字符'a'的指针,&p就会表示指向指针p的指针,这种指向一级指针的指针叫做二级指针,它的模式从上图也可以看到,它的类型是也还是指针,&p地址传入的话会从指向指针p存储的数据的第一个单元格开始访问,直到访问到'\0',这时候答案就会是随机值

 6.第六个,,&p就会表示指向指针p的指针,它的类型是也还是指针,访问权限也就是一个指针的大小,所以如上图,从p指针外的第一个单元格开始访问,它的值也是随机值

(注意:第5和6的随机值是没关联的,因为可能在p的四个单元格内就出现了'\0')

 7.第七个,p[0]代表字符'a',&它的地址,就代表取字符'a'的地址,这时候加一就指向了字符'b',代表指向字符'b'的指针,从b开始访问,所以结果为5

 8.第八个,p是一个指向常量字符串首字符’a'的指针,类型是指针,所以结果为4

 9.第九个,p是一个指针,&p是指向p指针的指针,它的类型其实还是一个指针,所以结果为4


三,总结

1. 我们看指针时,要理解它的意义,我们要注意它指向哪里,它的访问权限时多少。

    存储的地址可能相同,但是访问权限不同的话,它的意义也就不同了。

2. 利用sizeof时,siezof是计算类型的大小;它不会计算里面的表达式。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彭s

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

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

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

打赏作者

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

抵扣说明:

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

余额充值