C语言面试高频(指针)

指针

1 说说数组和指针的区别⭐⭐⭐⭐⭐

数组和指针在 C 和 C++ 等编程语言中是两个不同但又紧密相关的概念,以下从多个方面介绍它们的区别:

定义和本质

  • 数组:是一种复合数据类型,它是一组相同类型元素的集合,在内存中占据一段连续的存储区域。数组在定义时就确定了大小,这个大小在编译时就已经确定,后续不能再改变。例如 int arr[5]; 定义了一个包含 5 个 int 类型元素的数组。
  • 指针:是一种变量,其存储的是内存地址。指针可以指向任意类型的数据,包括数组、单个变量、函数等。指针的大小通常取决于操作系统的位数,例如在 32 位系统中指针大小为 4 字节,在 64 位系统中为 8 字节。例如 int *ptr; 定义了一个指向 int 类型数据的指针。

内存分配

  • 数组:数组的内存分配有两种情况。静态数组(如在函数外部或函数内部用 static 关键字修饰的数组)在程序的全局数据区或栈上分配内存;自动数组(在函数内部定义且没有 static 修饰)在栈上分配内存。数组的内存分配和释放由编译器自动处理,程序员无需手动干预。
  • 指针:指针本身的内存分配通常在栈上,但指针所指向的内存可以通过不同方式分配。如果指针指向静态变量或自动变量,那么这些变量的内存分配和数组类似;如果指针用于动态内存分配(如使用 malloccallocrealloc 或 new),则内存分配在堆上,需要程序员手动释放。

访问方式

  • 数组:数组元素可以通过下标直接访问,下标从 0 开始。例如 arr[2] 表示访问数组 arr 的第 3 个元素。这种访问方式直观且简单,编译器会根据数组的起始地址和元素的类型计算出要访问元素的实际地址。
  • 指针:指针访问数据需要通过解引用操作符 * 或使用指针算术运算。例如 *ptr 表示访问指针 ptr 所指向的内存中的值;ptr + 2 表示将指针向后移动 2 个元素的位置(移动的字节数取决于指针所指向的数据类型)。指针的访问方式更加灵活,但也更容易出错。

大小计算

  • 数组:使用 sizeof 运算符可以得到整个数组所占用的内存大小,即数组元素个数乘以每个元素的大小。例如 sizeof(arr) 可以得到数组 arr 的总字节数。通过 sizeof(arr) / sizeof(arr[0]) 可以计算出数组的元素个数。
  • 指针sizeof 运算符作用于指针时,得到的是指针本身的大小,而不是指针所指向的内存块的大小。例如 sizeof(ptr) 得到的是指针变量 ptr 占用的字节数,与它所指向的数据无关。

作为函数参数

  • 数组:当数组作为函数参数传递时,实际上传递的是数组首元素的地址,也就是一个指针。在函数内部,无法通过 sizeof 运算符得到数组的真实大小,因为此时数组已经退化为指针。
  • 指针:指针作为函数参数传递时,传递的也是指针本身的值(即内存地址)。函数可以通过这个指针修改指针所指向的内存中的值。

可变性

  • 数组:数组名代表数组的起始地址,它是一个常量指针,不能被赋值。例如 arr = ptr; 这样的赋值操作是不合法的。
  • 指针:指针是一个变量,可以被赋值为不同的地址。例如 ptr = &arr[0]; 或 ptr = (int *)malloc(sizeof(int) * 5); 都是合法的操作。

2 数组指针与指针数组的区别⭐⭐⭐⭐⭐

数组指针和指针数组是 C 和 C++ 等编程语言里容易混淆的两个概念,下面从定义、语法、内存布局和使用场景等方面来介绍它们的区别。

定义和语法

  • 数组指针:本质是一个指针,这个指针指向一个数组。声明时需要指定指针所指向数组的元素类型和数组大小。语法格式为类型 (*指针名)[数组大小]。例如int (*p)[5];,这里p就是一个指向包含 5 个int类型元素数组的指针。
  • 指针数组:本质是一个数组,数组中的每个元素都是指针。声明时要指定数组的大小和指针所指向数据的类型。语法格式为类型 *数组名[数组大小]。例如int *p[5];,表示p是一个包含 5 个int类型指针的数组。

内存布局

  • 数组指针:数组指针只占用一个指针大小的内存空间,用来存储它所指向数组的首地址。例如在 32 位系统中,数组指针通常占 4 字节,在 64 位系统中占 8 字节。它指向的是一个连续的数组内存块。
  • 指针数组:指针数组是一个数组,会占用多个指针大小的内存空间,具体大小取决于数组的元素个数。例如int *p[5];在 32 位系统中会占用 20 字节(5 个指针,每个 4 字节)。数组中的每个元素(指针)可以指向不同的内存地址,这些地址可以是分散的。

使用场景

  • 数组指针:常用于二维数组的处理,尤其是当二维数组作为函数参数传递时,使用数组指针可以方便地对二维数组进行操作。例如:

#include <stdio.h>

void printArray(int (*p)[3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    printArray(arr, 2);
    return 0;
}

在这个例子中,printArray函数的参数p就是一个数组指针,它指向一个包含 3 个int类型元素的数组。

  • 指针数组:常用于处理多个字符串或者多个不同的对象。例如,当需要存储多个字符串时,可以使用指针数组来存储每个字符串的首地址:

#include <stdio.h>

int main() {
    char *strArray[3] = {"apple", "banana", "cherry"};
    for (int i = 0; i < 3; i++) {
        printf("%s\n", strArray[i]);
    }
    return 0;
}

在这个例子中,strArray是一个指针数组,每个元素都是一个指向char类型(字符串)的指针。

初始化和赋值

  • 数组指针:初始化时需要将其指向一个数组的首地址。例如int arr[5] = {1, 2, 3, 4, 5,这里指向了数组。

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式/C++面试八股文 文章被收录于专栏

该专栏面向嵌入式开发工程师、C++开发工程师,包括C语言、C++,操作系统,ARM架构、RTOS、Linux基础、Linux驱动、Linux系统移植、计算机网络、数据结构与算法、数电基础、模电基础、5篇面试题目、HR面试常见问题汇总和嵌入式面试简历模板等文章。超全的嵌入式软件工程师面试题目和高频知识点总结! 另外,专栏分为两个部分,大家可以各取所好,为了有更好的阅读体验,后面会持续更新!!!

全部评论

相关推荐

25春招笔试完就开始面试了,提前给大家分享个去年的面经1.自我介绍2.可以说一下IOC和AOP吗?3.IOC有什么好处?3.Spring&nbsp;aop有几种代理模式?4.第二个项目是个人项目吗?5.Java的面向对象有几大特性?并说说你对这几个特性的理解6.关于Redis的了解,你在这个项目中用Redis做了什么?7.aof和rdb是什么技术?区别是什么?8.redis集群技术你了解吗?9.redis的一个key过来会分配到哪个机器上,算法是怎么样的呢?它有一套自己的算法,做一个映射10.hashmap和hashtable的区别?11.concurrent&nbsp;hashmap的阈值是多少?12.hash冲突的话有几种解决方式线性探测,平方探测,拉链法13.介绍一下hashmap的扩容因子,初始扩容因子是多少,初始数组容量是多少14.在你的项目中,kafka是用来做什么的?15.说一下redis的缓存雪崩,缓存穿透怎么解决的?16.缓存穿透怎么解决的?答:布隆过滤器&nbsp;追问:有其他的解决方案吗?17.redis热点key过期了,怎么处理?大量用户同时访问一个key,热点失效了,动态调整失效时间18.项目中的es是做什么的?问了论文,专利19.Java用了多久了?平时遇到过OOM的状况吗?介绍了一次full&nbsp;gc20.介绍一下JVM的内存模型21.CMS垃圾回收和G1垃圾回收的区别22.关于Zookeeper?23.介绍一下Spring,&nbsp;Spring&nbsp;MVC,&nbsp;Spring&nbsp;Boot,&nbsp;Spring&nbsp;Cloud?24.微服务之间的通信方式?RPC25.数据库用的是什么?MySQL&nbsp;哪个版本?26.讲一下数据库的事务?ACID特性27.MySQL事务的隔离级别:读未提交,读已提交,可重复读(默认隔离级别),串行化四个隔离级别分别解决了什么问题28.介绍一下七层网络架构29.介绍一下ARP协议,这是哪一层协议30.关于传输层协议了解哪些?TCP和UDP,介绍一下应用场景31.说一下Https和Http的区别32.Https的加密方式?&nbsp;对称加密+非对称加密33.说一下Http请求建立时候的错误代码34.手撕一下二叉树的中序遍历?先写递归,再写非递归小米公司校招内推码:&nbsp;BAD31ZQ&nbsp;投递链接:&nbsp;https://xiaomi.jobs.f.mioffice.cn/referral/campus/position/?token=NTsxNzQxNjU5NDI4MzU5OzcyNTI2MjA3NTAxMzI5MDQwNDQ7NzQyNzMxNTUyNTI5NjI5MTk0OA小米公司社招内推码:&nbsp;BAD31ZQ&nbsp;投递链接:&nbsp;https://xiaomi.jobs.f.mioffice.cn/referral/position/?token=NTsxNzQxNjU5NDgzMTM1OzcyNTI2MjA3NTAxMzI5MDQwNDQ7NzQyNzMyNzM3MjQyNzYyNDU1Ng#小米内推##小米##春招##面经##内推#
小米集团
|
校招
|
超多精选岗位
点赞 评论 收藏
分享
一共一个小时多一点点,两个面试官轮流进来,面试体验一般。中间问了很久的英语**面试官1:**1.上来就说我们公司做蓝牙,wifi的,不做Linux也不用高性能板子方向可能不是很匹配(我直接懵了,什么意思?)2.讲一下第一个项目3.讲一下第二个项目4.讲完了他说都是linux,有没用过简单一点的51&nbsp;32板子,然后我说第三个项目是32的5.怎么移植的freertos,步骤是什么6.了解wifi&nbsp;蓝牙吗(我说蓝牙之前有使用过,比较久了)7.然后就问了一下编程能力怎么样,我说还可以C/C++比较熟练8.然后问对他们公司有什么了解(我提前查过了,就说了啥,他也跟着说了说)9.然后问英语怎么样?(我说口语一般,读写看没问题,之前的一段工作经历,就是纯英文办公的)10.Please&nbsp;introduce&nbsp;you&nbsp;self?&nbsp;(自我介绍)11.What&nbsp;is&nbsp;your&nbsp;favorite&nbsp;sport&nbsp;(喜欢的运动)12.What&nbsp;are&nbsp;your&nbsp;strengths&nbsp;and&nbsp;weaknesses&nbsp;(优点和缺点)13.我优点英文说的,缺点我就说的中文,比较较真,比较执着,有时候可能就钻了牛角尖。然后追问我那你怎么就不执着了&nbsp;(我????)14.反问**面试官2:**1.自我介绍2.讲一下实习干了啥3.BMS这个项目介绍一下4.你使用了哪些硬件外设5.你说你用gpio模拟了i2c,怎么做的,为什么要这样做6.STM32的采样率和采样深度是多少7.rtos都做了哪些工作8.怎么配置rtos9.你说你做了保护功能,怎么保护的(解释看电压啥的)10.监测功能主要是监测什么东西11.gpio灯是咋控制的12.rtos都做什么工作了13.充电放电是怎么处理的,什么时候就认为满了14.充放电的曲线你知道是什么样子吗15.音视频同步怎么实现的16.时间基&nbsp;时间戳能不能详细说说17.怎么进行推流的,网络呢还是别的啥的18.说了rtmp,这个协议有啥特点呢19.最大的困难,怎么解决的,怎么排查的20.让用英文解释一个最熟悉的项目22.还有没有使用过别的开发板,我说有用过esp32啥的23.讲一下蓝牙协议24.反问
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务