指针与数组

简介: 指针与数组

说到C语言,可能大多数人会想到指针,并且大多数人也会因为指针从C语言入门到入土。所以可以毫不夸张的说,学好了C语言的指针也就学好了C语言。

 

那么今天我要分享的是指针与数组相结合的题目与相关知识。希望能够对大家有帮助。


首先我们先看下面的一组题目:


一维数组

#include<stdio.h>
int main()
{
    int a[]={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]));
    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));
    return 0;
}

大家觉得上面题目的答案会是什么呢?


我们想要做对这种类型的题,关键就在于我们是否能够知道数组名a在不同的地方代表的是什么意思。那么在这里我给大家分享一个小技巧:数组名只要单独放在sizeof内部,就像这样sizeof(a),这里的a就代表的是整个数组,sizeof(a)计算的是整个数组的大小。除此之外,数组名所表示的意思都是数组首元素的地址,在知道了这个技巧了之后,我们再看看上面的题目是不是觉得就很简单了呢?


26.png


我这里是在32位的环境下测试的,地址的大小是4个字节,准确一点来说其实答案是这样的:


16 4/8 4 4/8 4 4/8 16 4 4 4,看看是不是和你想得有些许差别呢?别急,这里我来给大家说说容易犯错误的地方:第一个sizeof(a),a单独放在sizeof内部,说明他计算的是整个数组的大小。而第二个sizeof(a+0),这里的a代表的是数组首元素地址,a+0之后还是数组首元素的地址,地址的大小在32位环境中是4个字节,在64位环境中占8个字节。第三个sizeof(*a),这里还是代表首元素地址,解引用之后就得到首元素的内容‘1’,而1又是整形类型,所以计算的大小是4个字节。后面的原理也大概相同,我在这里就不过多解释了,你们下去可以自行琢磨琢磨。


掌握了上面的内容后,我们再来看一组


字符数组

#include<stdio.h>
#include<string.h>
int main()
{
    char arr[]={'a','b','c','d','e','f'};
    printf("%d\n",sizeof(arr));
    printf("%d\n",sizeof(arr+0));
    printf("%d\n",sizeof(*arr));
    printf("%d\n",sizeof(arr[1]));
    printf("%d\n",sizeof(&arr));
    printf("%d\n",sizeof(&arr+1));
    printf("%d\n",sizeof(&arr[0]+1));
    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));
    return 0;
}

这些题呢?你是否依然能做对呢?


想要做对这些题,我们还需要了解{'a','b','c','d','e','f'}与"abcdef"的区别。{'a','b','c','d','e','f'}里面包含


'a' 'b' 'c' 'd' 'e' 'f'这些字符,而"abcdef"里面包含'a' 'b' 'c' 'd' 'e' 'f' '\0'。看出来区别了吗,{}里面不含有'\0',而""里面则含有'\0',所以我们在做题的时候需要额外的注意这些点。不仅如此,不知道你们是否也发现了我上面使用的计算数组元素个数所使用的工具也不一样,一个是sizeof,一个是strlen,那么这两个有什么区别呢?sizeof是你数组中有多少个元素n,就返回无符号整型n,而strlen则是从你给的地址开始计数,知道遇到'\0'。所以上面的答案也就是。


27.png


不对啊,答案对不对我们先不说,按理来说,屏幕上不是应该打印14个数字吗?怎么才9个数字呢?我们来看看第十个strlen(*arr),arr代表的是首元素的地址,而解引用的话就得到了第一个元素'a',对照ASCII表,我们可以将'a'转换为97,所以这里就相当于strlen(97),我们看看strlen的参数


28.png


strlen的参数是地址啊,但是我们传进去的是数字该怎么搞啊。这里97将会被转换为地址即0x000061,而这个地址又不一定在数组中,所以就导致了非法访问,这就很危险了,所以我们还是得多注意点。


是不是这些很有意思呢?我们继续看一组:

#include<stdio.h>
#include<string.h>
int main()
{
    char arr[]="abcdef";
    printf("%d\n",sizeof(arr));
    printf("%d\n",sizeof(arr+0));
    printf("%d\n",sizeof(*arr));
    printf("%d\n",sizeof(arr[1]));
    printf("%d\n",sizeof(&arr));
    printf("%d\n",sizeof(&arr+1));
    printf("%d\n",sizeof(&arr[0]+1));
    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));  //这里&arr+1跳过的是整个数组
    printf("%d\n",strlen(&arr[0]+1));
    return 0;
}

这里我就不做过多的解释了,紧跟着下面图片的答案是error,error,6,随机值,5


29.png

接下来就给大家上点难度了。


二维数组

#include<stdio.h>
#include<string.h>
int main()
{
    int a[3][4]={0};
    printf("%d\n",sizeof(a));
    printf("%d\n",sizeof(a[0][0]));
    printf("%d\n",sizeof(a[0]));
    printf("%d\n",sizeof(a[0]+1));
    printf("%d\n",sizeof(*(a[0]+1)));
    printf("%d\n",sizeof(a+1));
    printf("%d\n",sizeof(*(a+1)));
    printf("%d\n",sizeof(&a[0]+1));
    printf("%d\n",sizeof(*(&a[0]+1)));
    printf("%d\n",sizeof(*a));
    printf("%d\n",sizeof(a[3]));
    return 0;
}


答案是什么呢?是不是感觉有点懵啊,别着急,其实二维数组跟一维数组是一个原理,只是有点点的差异。sizeof(a)计算的也还是整个数组的大小,而除了a单独放在sizeof内部之外,a还是代表的首元素地址,只是这里的首元素地址与一维数组的有点差异,二维数组的首元素地址代表的是第一行数组的地址,a[0]和a+0代表第一行首元素地址,a[1]和a+1代表的是第二行首元素的地址,我们也可以这样看,当a[i]或a+i单独放在sizeof内部是还是相当于计算的第i+1行的所有元素。这样上面的题目是不是也迎刃而解了呢?看看答案是不是跟你的一样呢?


30.png


总结


数组名的意义:

1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。

2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

3.除此之外所有的数组名都表示首元素的地址。

 

好了这些就是我今天分享的全部内容了,谢谢大家的观看

相关文章
|
1月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
37 3
|
23天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
27天前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
27天前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
27天前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
1月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
51 4
|
1月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
48 2
|
1月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
39 1
|
2月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
2月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。