# 基础知识
# 常见问题
# 数字含义
- 条件判断、逻辑运算等方面的约定俗成的惯例
- 1 表示真或者真值。
- 0 表示假或者假值。
- 函数的返回值
- 0 表示成功,
- 非 0 表示失败
main 函数 return 0, 代表成功还是失败
# 内存管理
malloc (): 用于动态分配内存空间。其原型为 void* malloc (size_t size),其中 size 参数表示需要分配的字节数。malloc () 返回一个指向分配内存起始地址的指针,如果分配失败,则返回 NULL。
calloc (): 用于动态分配并初始化内存空间。其原型为 void* calloc (size_t num, size_t size),其中 num 为元素个数,size 为每个元素的大小。calloc () 返回一个指向分配内存起始地址的指针,如果分配失败,则返回 NULL。与 malloc () 不同的是,calloc () 分配的内存会被初始化为零。
realloc (): 用于重新分配已分配内存的大小。其原型为 void* realloc (void* ptr, size_t size),其中 ptr 是之前分配内存的指针,size 是重新分配的字节数。如果分配成功,则返回一个指向新分配内存起始地址的指针,如果分配失败,则返回 NULL。注意,如果重新分配失败,原始内存块仍然保持不变,不会被释放。
free (): 用于释放动态分配的内存空间。其原型为 void free (void* ptr),其中 ptr 是需要释放的内存块的指针。一旦释放,该内存块就可以被重新分配或使用。
- 代码示例
#include <stdio.h>#include <stdlib.h>int main() {
int *ptr1, *ptr2, *ptr3;
// 使用 malloc () 分配 5 个整型空间ptr1 = (int*)malloc(5 * sizeof(int));
if (ptr1 == NULL) {
printf("内存分配失败\n");
return 1;
}// 使用 calloc () 分配 3 个整型空间,并初始化为 0ptr2 = (int*)calloc(3, sizeof(int));
if (ptr2 == NULL) {
printf("内存分配失败\n");
free(ptr1); // 释放之前分配的内存
return 1;
}// 使用 realloc () 扩展 ptr1 指向的内存空间为 8 个整型ptr3 = (int*)realloc(ptr1, 8 * sizeof(int));
if (ptr3 == NULL) {
printf("内存分配失败\n");
free(ptr1); // 释放之前分配的内存
free(ptr2); // 释放之前分配的内存
return 1;
} else {
ptr1 = ptr3; // 使 ptr1 指向扩展后的内存空间
}// 释放内存free(ptr1);
free(ptr2);
return 0;
}在这个示例中,我们:
- 使用 malloc () 分配了一块大小为 5 个整型的内存空间,并将其指针赋给 ptr1。
- 使用 calloc () 分配了一块大小为 3 个整型的内存空间,并将其指针赋给 ptr2。
- 使用 realloc () 对 ptr1 指向的内存空间进行了扩展,使其大小为 8 个整型,并将扩展后的指针赋给 ptr3。
- 最后,我们释放了分配的内存空间,以避免内存泄漏。
# 指针基础知识
基础知识:
- 指针变量: 指针变量是用来存储内存地址的变量。声明一个指针变量时,需要指定指针变量的类型,表示它所指向的数据的类型。
- 取址运算符 (&): 取址运算符用于获取变量的内存地址。例如,&a 表示变量 a 的地址。
- 间接访问运算符 (*): 间接访问运算符用于获取指针所指向的数据。例如,*ptr 表示获取指针 ptr 所指向的数据。
- 空指针 (NULL): 空指针是一个特殊的指针值,表示不指向任何有效的内存地址。在 C 语言中,可以使用 NULL 宏来表示空指针。
- 指针算术: 指针可以进行算术运算,例如加法、减法等,用来移动指针的位置。
- 示例:下面是一个关于一级指针和二级指针的示例:
#include <stdio.h>int main() {
int num = 10;
int *ptr1; // 一级指针
int **ptr2; // 二级指针
// 将 num 的地址赋给 ptr1ptr1 = #
// 将 ptr1 的地址赋给 ptr2ptr2 = &ptr1;
// 输出 num 的值printf("num 的值为:%d\n", num);
// 使用一级指针访问 num 的值printf("通过一级指针访问 num 的值:%d\n", *ptr1);
// 使用二级指针访问 num 的值printf("通过二级指针访问 num 的值:%d\n", **ptr2);
return 0;
}- 解释说明
- 我们首先声明了一个整型变量 num,并赋值为 10。
- 然后声明了一个一级指针 ptr1,将 num 的地址赋给 ptr1。
- 接着声明了一个二级指针 ptr2,将 ptr1 的地址赋给 ptr2。
- 最后通过一级指针和二级指针分别访问了 num 的值,输出结果相同,都为 10。
- 解释说明
- 示例:下面是一个示例,演示了数组指针、函数指针以及容易混淆的指针写法:
#include <stdio.h>// 函数声明int add(int a, int b);
int subtract(int a, int b);
int main() {
// 数组指针示例int arr[5] = {1, 2, 3, 4, 5};
int *ptr_arr = arr; // 数组名即为数组首元素的地址,ptr_arr 指向数组 arr 的第一个元素
printf("数组第一个元素的值:%d\n", *ptr_arr); // 输出数组第一个元素的值
// 函数指针示例int (*func_ptr)(int, int); // 声明一个指向接受两个整型参数、返回整型的函数指针
func_ptr = &add; // 函数名即为函数的地址,func_ptr 指向函数 add
printf("add(3, 4) 的结果:%d\n", func_ptr(3, 4)); // 调用函数指针执行 add (3, 4)
func_ptr = &subtract; //func_ptr 指向函数 subtract
printf("subtract(5, 2) 的结果:%d\n", func_ptr(5, 2)); // 调用函数指针执行 subtract (5, 2)
// 容易混淆的指针写法示例int x = 10;
int *ptr1, ptr2; // 这里 ptr1 是指针变量,ptr2 是整型变量,而不是两个指针变量
ptr1 = &x;
ptr2 = x;
printf("ptr1 指向的值:%d\n", *ptr1); // 输出指针变量 ptr1 指向的值
printf("ptr2 的值:%d\n", ptr2); // 输出整型变量 ptr2 的值
return 0;
}// 函数定义int add(int a, int b) {
return a + b;
}int subtract(int a, int b) {
return a - b;
}- 解释说明
- 首先定义了一个整型数组 arr,然后声明了一个指向整型数组的指针 ptr_arr,并将数组 arr 的首地址赋值给了 ptr_arr。通过 ptr_arr 指针可以访问数组中的元素。
- 然后定义了两个函数 add 和 subtract,用来执行加法和减法操作。接着声明了一个函数指针 func_ptr,并通过赋值将其指向了 add 和 subtract 函数。通过 func_ptr 指针可以动态调用这两个函数。
- 最后演示了容易混淆的指针写法,声明了一个指针变量 ptr1 和一个整型变量 ptr2。在这种写法中,需要注意变量的声明方式,以避免产生混淆。
- 解释说明
# 嵌入式开发的编程语言
C 语言:
- 优点:
足够底层,直接操作硬件,对于资源受限的嵌入式系统更加适用。
通常编译后的代码较小,执行速度较快。
更接近硬件的抽象层,对于对内存、CPU 等底层资源的控制更为直接。 - 缺点:
缺乏面向对象的特性,不够抽象,有时可能会导致代码复杂度较高。
不够灵活,需要手动管理内存,容易出现内存泄漏和指针错误。
- 优点:
C++:
- 优点:
支持面向对象编程,具有封装、继承和多态等特性,使代码更加模块化和可维护。
有丰富的标准库和第三方库,提供了更多高级的数据结构和算法。
拥有更多的编程范式,如模板元编程等,能够提供更好的代码重用和泛化能力。 - 缺点:
生成的代码通常较大,可能会增加系统的资源消耗。
需要更多的运行时支持,对于资源受限的嵌入式系统可能不够适用。
C++ 的复杂性可能会导致开发过程更为繁琐,需要更多的学习和理解。
- 优点:
综合考虑,对于资源受限的嵌入式系统,或者对性能和资源消耗要求较高的应用场景,C 语言可能更为合适。而对于需要更高层次抽象和更灵活的编程模型的应用,以及对代码的可维护性和可重用性有更高要求的项目,C++ 可能更适合。
使用方式
浏览模式
如何编译