(嵌入式八股)No.1 C语言(3)

3.1 指针(重点、重中之重)

指针是 C 语言中一个非常强大且灵活的特性,它允许程序直接操作内存地址。指针可以用于多种用途,包括动态内存分配、访问数组元素、实现数据结构(如链表和树)等。

指针是一个变量,其存储的内容是另一个变量的地址。(好了,你知道指针就是一个地址就学完了(bushi))哈哈哈哈哈开玩笑呢

推荐一本书《C和指针》!!!

int a = 10;
int *p = &a;  // p 中保存着 a 的地址
a:普通变量,存放的是值 10;
p:指针变量,存放的是 a 的地址;
*p:解引用操作,取出 p 指向的地址中保存的值(即 a 的值)。

指针的四层关系

表达式

含义

a

变量本身(值)

&a

变量的地址

p

指针变量本身(保存地址)

*p

指针指向的值(间接访问)

指针声明和类型

int    *p1;   // 指向 int
char   *p2;   // 指向 char
float  *p3;   // 指向 float
void   *p4;   // 通用指针(不能直接解引用)
 指针类型决定了解引用后的数据解释方式(即:从内存中取多少字节、如何解释)。

必考:指针与数组(面试也会问)

指针与数组的区别?( easy)

  1. 数组名是常量(指向固定内存),不能修改;
  2. 指针是变量,可以指向别的地址;
  3. sizeof(arr) 是整个数组大小;
  4. sizeof(ptr) 是指针大小(通常 4 (32 位系统)或 8 字节(64 位系统))。

一维数组与指针

intarr[3] = {10, 20, 30};
int *p = arr;  // arr 等价于 &arr[0]
printf("%d\n", *(p+1)); // 输出 20
  1. 关系:问的比较多的就是指针和数组的关系!
  2. arr → 数组首元素地址&arr[0] → 数组首元素地址
  3. *p → 等价于 arr[0]*(p+i) → 等价于 arr[i]

二维数组与指针

int a[2][3] = {{1,2,3},{4,5,6}};
int (*p)[3] = a;  // p 指向含 3 个 int 的一维数组
printf("%d\n", *(*(p+1)+2)); // 输出 6

说明:p 是一个“指向长度为 3 的 int 数组”的指针;

p+1 指向下一行;*(p+1) 是该行的首地址;

*(p+1)+2 指向该行的第 3 个元素。

指针与函数

指针作函数参数(传址调用)

void swap(int *a, int *b) 
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

指针函数(这个面试会和函数指针一起考)

指针函数是一个返回值为指针的函数。它的返回值是一个指针类型。

int* func() 
{
    static int x = 10;
    return &x;
}

函数指针

函数指针是一个指针变量,它指向一个函数的入口地址。通过函数指针,可以像调用普通函数一样调用被指向的函数。

int add(int a, int b) { return a + b; }int (*pf)(int, int) = add;printf("%d\n", pf(3,4)); // 输出 7

函数指针可以用于 回调函数、事件处理(动态选择函数:根据条件动态调用不同的函数)、函数表:将多个函数指针存储在数组中,通过索引调用不同的函数 等。

野指针问题

什么是野指针

(1)野指针就是指向未知位置的指针。

(2)指针局部变量未初始化会造成野指针,使用 free 后没有将指针置为 NULL 也会造成野指针。

野指针的危害

(1)指向不可访问的地址,譬如内核空间:触发段错误。

(2)指向一个可访问的、没什么意义的地址,譬如空闲栈空间:不会触发明显错误,但会留下安全隐患。

(3)指向一个访问的被程序使用的地址,譬如说一个变量:导致数据被损害或者程序崩溃,危害最大。

怎样避免野指针

(1)定义指针时初始化为 NULL 或者绑定一个可用地址空间。

(2)指针使用完之后,将其赋值为 NULL。

#include <stdio.h>

int main() {
    int *ptr;        // 未初始化,此时 ptr 是一个野指针(指向随机地址)
    int *ptr = NULL;     // 必须初始化
    // 尝试访问野指针指向的内存(危险操作!)
    printf("%d\n", *ptr);   // 未定义行为:可能打印随机值、崩溃或产生其他不可预料的结果
    return 0;
}

/*释放后未置空 */
#include <stdio.h>
#include <stdlib.h>
int main() {
    int *ptr = (int*)malloc(sizeof(int));
    *ptr = 42;
    free(ptr);       // 内存已释放,但 ptr 仍指向原地址(此时成为野指针)
    // 错误:继续使用已释放的指针    应该先   ptr = NULL ;  
    printf("%d\n", *ptr);   // 未定义行为
    return 0;
}




3.2 位运算

(有的面试官会考察,或者笔试题里面会出现)(芯片厂最喜欢考了)

位操作符

1.位与&

(1)注意:位与是&,逻辑与是&&。举例 0xAA&0xF0=0xA0,0xAA && 0xF0=1

2.位或|

(1)注意:位或是 |,逻辑或是||。

3.位取反~

(1)注意:C 语言中位取反是~,逻辑取反是!.

4.位异或^

(1)0 或 1 与 1 位异或就会取反,0 或 1 与 0 位异或则不变。

5.位左移、位右移

(1)对于无符号数:

①左移时右侧补 0,相当于逻辑移位。

②右移时左侧补 0,相当于逻辑移位。

(2)对于有符号数:

①左移时右侧补 0,叫算术移位,相当于逻辑移位。

②有右移时左侧补符号位,正数补 0 负数补 1,叫算术移位。

(3)嵌入式中使用的移位都是无符号数移位。

&,|,^在操作寄存器时的特殊作用

1.寄存器的操作要求

  (1)ARM 是内存与 IO 统一编制的(x86 则不是),读写寄存器就是操控硬件。

  (2)如何做到设定特定位时不影响其它位?答案是:读-改-写三部曲。

2.特定位清零用&

3.特定位置 1 用|

4.特定位取反

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

泻湖花园嵌入式Offer指南 文章被收录于专栏

从入门到上岸,一站式搞定求职! 本硕纯机械,无竞赛无论文,后转行嵌入式软件开发(因为课题组师哥转嵌入式拿到30Woffer之后狠狠心动),秋招最终收获35W+offer可以为27届或者28届的的UU们提供参考,可以关注一下!!!

全部评论
很详细的内容 感谢分享
1 回复 分享
发布于 03-03 19:05 陕西
upup希望大家看到
点赞 回复 分享
发布于 03-03 22:35 山东
C语言,这代码能力,算是面试的最基本要求了
点赞 回复 分享
发布于 03-03 22:06 陕西

相关推荐

评论
7
10
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务