嵌入式相关知识点合集(1)仅供自己复习加深参考,若有错误请高人斧正
其中全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。void func(int arr[]){//实际上等价于 int *arr。// 指针在栈上,指向常量区的字符串。printf("%d的立方: %d\n", x, x * x * x);命令行参数区:存放命令行的参数和环境变量的值,如通过main()函数传递的
第一部分:C语言
1.C语言的内存模型:
程序代码区:存放函数体的二进制代码;
静态数据区:也称全局数据区,包含的数据类型比较多,如全局变量、静态变量、一般常量、字符串常量。其中全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。常量数据存放在另一个区域。静态数据区的内存在程序结束后由操作系统释放。
堆区:一般由程序员分配和释放,若程序员不释放,程序运行结束后由操作系统回收。malloc(),calloc()、free()等函数操作的就是这块内存。
栈区:由系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
命令行参数区:存放命令行的参数和环境变量的值,如通过main()函数传递的值。

2 指针与数组区别
数组是相同类型元素的连续集合,数组名代表整个内存块
指针是一个变量,存储内存地址,只存地址,需另分配目标内存
(1)内存分配方式与sizeof运算结果不同
int arr[5]; // 编译器分配20字节连续内存(假设int为4字节)
int *ptr; // 只分配指针变量本身的内存(通常4或8字节)
ptr = malloc(20); // 动态分配内存,ptr指向这块内存
sizeof(arr); // 返回20(整个数组大小)
sizeof(ptr); // 返回指针大小(4或8字节)
(2)赋值和修改
int arr1[5], arr2[5];
int *p1, *p2;
// 数组不能直接赋值
// arr1 = arr2; // 错误!数组名是常量指针,不能赋值
// 指针可以赋值
p1 = arr1; // 正确
p1 = p2; // 正确
(3)地址运算
int arr[5];
int *p = arr;
p++; // 正确,p现在指向arr[1]
// arr++; // 错误!数组名是常量,不能修改
(4)作为函数参数时的退化
当数组作为函数参数传递时,会退化为指针:
void func(int arr[]) { // 实际上等价于 int *arr
// sizeof(arr) 返回指针大小,不是数组大小
}
(5)初始化和存储位置
char str1[] = "hello"; // 栈上分配数组,可修改
char *str2 = "world"; // 指针在栈上,指向常量区的字符串
(6)容易混淆的点
数组名在大多数表达式中会退化为指向首元素的指针
arr[i]和*(arr+i)等价
但&arr和&ptr的含义不同:
int arr[5];
int *p = arr;
&arr; // 类型是 int(*)[5],指向整个数组
&p; // 类型是 int**,指向指针变量
3.野指针
野指针指向不可用的内存或未初始化的指针,使用野指针会导致未定义行为,通常是程序崩溃。
指针本身即存储地址的变量可以任意赋值,但通过指针访问/修改内存(解引用)时,必须确保指针指向有效的、已分配的内存。未初始化的指针存储的是随机地址,解引用会访问非法内存,导致段错误或未定义行为。
(1)未初始化的指针
int *p; //未初始化,随机值
*p = 10;//错误,会访问位置内存
正确示例:
int x =5 ;
int *p = &x; //指针指向变量x
*p =10; //修改x的值为10
(2)指针被释放后未置空
int *p = (int*)malloc(sizeof(int));
free(p);
*p =20; //错误,因为已经释放p,无法访问已释放内存
正确示例:
int *p = (int*)malloc(sizeof(int));
*p = 20; // 正确:修改动态分配的内存
free(p);
(3)超出作用域
int* func(){
int a = 10;
return &a; //返回局部变量的地址
}//函数结束,a被销毁,返回的指针变为野指针
4.函数指针
函数指针定义为指向函数的指针变量,可以像调用函数一样通过指针调用。
返回类型 (*指针名)(参数类型列表);
#include <stdio.h>
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int main() {
// 声明函数指针
int (*func_ptr)(int, int);
// 指向add函数
func_ptr = add; // 或 func_ptr = &add;
printf("5 + 3 = %d\n", func_ptr(5, 3));
// 指向sub函数
func_ptr = sub;
printf("5 - 3 = %d\n", func_ptr(5, 3));
return 0;
}
typedef简化
typedef int (*Operation)(int, int);
Operation op = add; // 更清晰的声明
printf("%d\n", op(5, 3));
5.指针函数
指针函数定义为返回指针的函数,即函数的返回值是指针
返回类型* 函数名(参数列表)
#include <stdio.h>
#include <stdlib.h>
// 返回int指针的函数
int* create_array(int size) {
int *arr = (int*)malloc(size * sizeof(int));
for(int i = 0; i < size; i++) {
arr[i] = i * 2;
}
return arr; // 返回动态分配内存的指针
}
int main() {
int *ptr = create_array(5);
for(int i = 0; i < 5; i++) {
printf("%d ", ptr[i]);
}
free(ptr); // 记得释放内存
return 0;
}
注:调用者负责释放返回的动态内存。
6.函数指针数组
函数指针数组定义数组的元素是函数指针,用于实现跳转表或命令表
返回类型 (*数组名[数组大小])(参数类型列表);
示例:计算器
#include <stdio.h>
#include <string.h>
double add(double a, double b) { return a + b; }
double sub(double a, double b) { return a - b; }
double mul(double a, double b) { return a * b; }
double div(double a, double b) { return b != 0 ? a / b : 0; }
int main() {
double (*calc[4])(double, double) = {add, sub, mul, div};
char operators[] = {'+', '-', '*', '/'};
double x = 10.5, y = 2.5;
char op = '*';
for(int i = 0; i < 4; i++) {
if(operators[i] == op) {
printf("%.2f %c %.2f = %.2f\n", x, op, y, calc[i](x, y));
break;
}
......
return 0;
}
7.回调函数机制
#include <stdio.h>
// 回调函数类型定义
typedef void (*Callback)(int);
// 处理函数,接受回调函数作为参数
void process_data(int data[], int size, Callback callback) {
for(int i = 0; i < size; i++) {
callback(data[i]); // 调用回调函数
}
}
// 各种回调函数
void print_square(int x) {
printf("%d的平方: %d\n", x, x * x);
}
void print_cube(int x) {
printf("%d的立方: %d\n", x, x * x * x);
}
int main() {
int data[] = {1, 2, 3, 4, 5};
int size = sizeof(data) / sizeof(data[0]);
// 使用不同的回调函数处理数据
printf("=== 平方计算 ===\n");
process_data(data, size, print_square);
printf("\n=== 立方计算 ===\n");
process_data(data, size, print_cube);
return 0;
}
更多推荐



所有评论(0)