嵌入式c语言知识点合集

1,函数指针和指针函数

函数指针是指向函数的指针,用于存储函数在内存中的地址。

用法:回调函数:void (*functionCallback)(int a, int b);

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    int (*operation)(int, int);
    
    operation = add;
    printf("加法结果:%d\n", operation(5, 3));
    
    operation = subtract;
    printf("减法结果:%d\n", operation(5, 3));
    
    return 0;
}

指针函数就是函数的返回值是指针。

用法:创建一个结构体,返回一个结构体指针

#include <stdio.h>
#include <stdlib.h>

int* create_array(int size) {
    int* arr = (int*)malloc(size * sizeof(int));
    if (arr == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    for (int i = 0; i < size; i++) {
        arr[i] = i * 10;
    }
    return arr;
}

int main() {
    int size = 5;
    int* array = create_array(size);
    
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
    
    free(array);
    return 0;
}

区别:前两个字,返回函数,就是函数指针;返回指针,就是指针函数。

2,指针的大小

指针的大小取决于编译器和目标平台的架构。通常情况下,指针的大小与处理器的位数有关:

32位系统就是32bit (4B); 64位系统就是64bit(8B)。

直接用sizeof即可获取指针大小。

3,sizeof和strlen的区别

sizeof:编译时运算符,用于计算数据类型或变量所占的内存字节数。它可以作用于任意数据类型,包括基本类型、数组、结构体等。计算结果包含字符串末尾的空字符 '\0'

对于数组,sizeof 返回整个数组的大小;而对于指针,sizeof 返回指针本身的大小,与其指向的数据无关。

strlen:运行时函数,定义在 <string.h> 头文件中,用于计算以空字符 '\0' 结尾的字符串的实际长度,即字符的个数,不包含末尾的 '\0'

sizeof 在编译时确定大小,而 strlen 在运行时计算长度。

4,c语言中内存分配的方式有几种?

  • 栈区(Stack):由编译器自动分配和释放,主要用于存储函数的参数、局部变量等。栈区的内存由操作系统自动管理,特点是存取速度快,但空间有限。

  • 堆区(Heap):由程序员手动分配和释放,使用如 mallocfree 等函数进行管理。堆区适合存储需要动态分配的内存块,生命周期由程序员控制,若未及时释放可能导致内存泄漏。

  • 全局/静态存储区(Global/Static Storage):存放全局变量和静态变量。初始化的全局变量和静态变量存放在一块区域,未初始化的则存放在相邻的另一块区域。程序运行期间,这些变量一直存在,内存由系统在程序加载时分配,程序结束时释放。

  • 常量区(Constant Area):用于存放常量数据,如字符串常量等。该区域的内存通常是只读的,程序结束后由系统释放。

  • 代码区(Code Area):存放程序的机器指令,即编译后的二进制代码。该区域的内存由系统管理,通常也是只读的,以防止程序意外修改自身的指令。

5,struct和union的区别:

内存分配方式:

  • 结构体(struct:每个成员都有独立的内存空间,结构体的总大小是各成员大小之和(考虑内存对齐)。

  • 联合体(union:所有成员共享同一块内存,联合体的大小等于最大成员的大小

数据存储特点:

  • 结构体:可以同时存储所有成员的值,各成员互不干扰。

  • 联合体:在同一时间只能存储一个成员的值,修改一个成员会影响其他成员,因为它们共享内存。

使用场景:

  • 结构体:适用于需要同时存储多个不同类型数据的情况,例如表示一个学生的姓名、年龄和成绩。

  • 联合体:适用于需要在同一内存位置存储不同类型数据的情况,例如处理多种数据类型的协议数据

#include <stdio.h>
#include <string.h>

struct ExampleStruct {
    char a;
    int b;
    short c;
};

union ExampleUnion {
    char a;
    int b;
    short c;
};

int main() {
    struct ExampleStruct s;
    union ExampleUnion u;

    printf("Size of struct: %zu bytes\n", sizeof(s));
    printf("Size of union: %zu bytes\n", sizeof(u));

    s.a = 'A';
    s.b = 100;
    s.c = 10;
    printf("Struct values: a = %c, b = %d, c = %d\n", s.a, s.b, s.c);

    u.b = 100;
    printf("Union values after setting b: a = %c, b = %d, c = %d\n", u.a, u.b, u.c);

    u.a = 'A';
    printf("Union values after setting a: a = %c, b = %d, c = %d\n", u.a, u.b, u.c);

    return 0;
}

6,野指针是什么?什么原因会导致野指针?

野指针是指那些指向已释放或未分配内存区域的指针。

导致野指针的主要原因:

  1. 指针未初始化:声明指针变量后未对其进行初始化,此时指针包含不确定的值,可能指向任意内存地址。

int *ptr; // 未初始化的指针
*ptr = 10; // 未定义行为,可能导致程序崩溃

2,内存释放后未将指针置为 NULL:使用 freedelete 释放内存后,指针仍然指向原来的内存地址,但该内存已不再有效。

int *ptr = (int *)malloc(sizeof(int));
*ptr = 10;
free(ptr); // 释放内存
// ptr 仍然指向已释放的内存,成为野指针

3,指针越界访问:当指针操作超出其合法范围,导致指向未分配或无效的内存区域。

int array[5] = {1, 2, 3, 4, 5};
int *ptr = array;
for (int i = 0; i < 10; i++) {
    printf("%d\n", *(ptr + i)); // 当 i >= 5 时,发生越界访问
}

避免野指针的措施:

1,指针初始化:在声明指针时,将其初始化为 NULL

2,内存释放后将指针置为 NULL:释放内存后,立即将指针设置为 NULL,防止再次误用。

3,使用前检查指针有效性:在使用指针前,检查其是否为 NULL

4,避免指针越界操作:确保指针操作在合法范围内,防止越界访问。

7,define和typedf的区别

#define

  • 预处理指令#define 是一种预处理指令,用于在编译前进行简单的文本替换。

  • 宏定义:常用于定义常量、宏函数或进行条件编译。

  • 无类型检查:由于只是文本替换,编译器不会对其进行类型检查,可能导致潜在的错误。

typedef

  • 类型定义关键字typedef 用于为已有类型定义新的类型别名。

  • 增加可读性:通过为复杂的类型定义简短的别名,提高代码的可读性和可维护性。

  • 类型安全typedef 定义的别名在编译时会进行类型检查,确保类型安全。

主要区别:

  1. 处理阶段#define 在预处理阶段进行文本替换;typedef 在编译阶段处理。

  2. 类型检查#define 不进行类型检查,可能引发潜在错误;typedef 会进行类型检查,确保类型安全。

  3. 作用范围#define 的宏在整个代码中全局有效;typedef 定义的类型别名遵循作用域规则,只在定义的作用域内有效。

  4. 适用场景#define 适用于定义常量、宏函数等;typedef 适用于为类型定义别名,特别是复杂类型。

使用 #define 定义指针类型时,可能会引发意想不到的问题。例如:

#define PCHAR char *
PCHAR a, b;

预处理后,ab 的类型分别是 char* achar b,这可能不是预期的结果。而使用 typedef 定义则不会出现此问题.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值