嵌入式面试2(c相关)
目录
1.C语言中static、const、volatile关键字用法区别;
static的用法(定义和用途)
const的用法(定义和用途)
volatile (英文意思为易变的) 作用和用法:
2.C语言中,const 和 static 的区别,char * const 和 const * char的区别
3.变量声明和定义的区别:
4.C语言编译后的内存分布
5.C语言内存分区,未定义的全局变存放在哪个区
6.静态局部变量存储在静态区,那么静态区的创建和消失是在什么时候?
7.变量加入static以后在内存中存储位置的变化
8.在windows里面运行了多个进程,其中一个进程执行完了,它的静态区会如何处理
9.连续调用同一个函数两次,它的局部变量初始化结果是否会一致?
10.静态局部变量与局部变量的区别?为什么局部变量未定义时,每次初始化的结果是不确定的?是个真随机数还是个伪随机数?
11.快排时间复杂度怎么计算的
12.用熟悉的编译器手写栈和冒泡排序
1.C语言中static、const、volatile关键字用法区别;
static的用法(定义和用途)
1)用static修饰局部变量:使其变为静态存储方式(静态数据区),那么这个局部变量在函数执行完成之后不会被释放,而是继续保留在内存中。
2)用static修饰全局变量:使其只在本文件内部有效,而其他文件不可连接或引用该变量。
3)用static修饰函数:对函数的连接方式产生影响,使得函数只在本文件内部有效,对其他文件是不可见的(这一点在大工程中很重要很重要,避免很多麻烦,很常见)。这样的函数又叫作静态函数。使用 静态函数的好处是,不用担心与其他文件的同名函数产生干扰,另外也是对函数本身的一种保护机制。
const的用法(定义和用途)
const主要用来修饰变量、函数形参和类成员函数:
1)用const修饰常量:定义时就初始化,以后不能更改。
2)用const修饰形参:func(const int a){};该形参在函数里不能改变
3)用const修饰类成员函数:该函数对成员变量只能进行只读操作,就是const类成员函数是不能修改成员变量的数值的。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1.const int a;
2.int const a;
3.const int *a;
4.int * const a;
5.int const * a const;
前两个的作用是一样,a是一个常整型数。
常指针从右往左读,以*为分界
第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
volatile (英文意思为易变的) 作用和用法:
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量在内存中的值,而不是使用保存在寄存器里的备份(虽然读写寄存器比读写内存快)。
以下几种情况都会用到volatile:
并行设备的硬件寄存器(如:状态寄存器)
一个中断服务子程序中会访问到的非自动变量
多线程应用中被几个任务共享的变量
2.C语言中,const 和 static 的区别,char * const 和 const * char的区别
const 关键字用于定义常量,即在程序运行期间不可修改的值。const 可以用于修饰变量、函数参数和函数返回值。使用 const 可以提高程序的可读性和安全性。
static 关键字用于定义静态变量或函数。静态变量在程序运行期间只会被初始化一次,而静态函数只能在当前文件中被调用。使用 static 可以控制变量和函数的作用域,避免命名冲突和不必要的访问。
char * const 和 const * char 的区别在于指针指向的内容是否可以被修改。char * const 表示指针本身是常量,即指针指向的地址不可修改,但指针指向的内容可以修改;而 const * char 表示指针指向的内容是常量,即指针指向的内容不可修改,但指针本身可以修改。
3.C语言字节对齐、结构体对齐
什么是字节对齐?
在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在结构中,编译器为结构的每个成员按其自然边界(alignment)分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
为了使CPU能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对齐”. 比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除.
字节对齐有什么作用?
需要字节对齐的根本原因在于CPU访问数据的效率问题。假设变量的地址不是自然对齐,取它的值的话需要访问多次内存,而如果变量在自然对齐位置上,则只要一次就可以取出数据。
正确处理字节对齐
对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐:
数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。
联合 :按其包含的长度最大的数据类型对齐。
结构体: 结构体中每个数据类型都要对齐。
结构体各成员的起始位置相对于结构体变量的起始位置的偏移量,应该为该结构体成员类型所占字节数与pack(n)的n取最小值的倍数
• 结构体变量所占字节数应该是结构体各成员所占字节数的最大值与pack(n)的n取最小值
举例说明
例1
struct test
{
char x1;
short x2;
float x3;
char x4;
};
由于编译器默认情况下会对这个struct作自然边界(有人说“自然对界”我觉得边界更顺口)对齐,结构的第一个成员x1,其偏移地址为0,占据了第1个字节。第二个成员x2为short类型,其起始地址必须2字节对界,因此,编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然边界地址上,在它们前面不需要额外的填充字节。在test结构中,成员x3要求4字节对界,是该结构所有成员中要求的最大边界单元,因而test结构的自然对界条件为4字节,编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。
例2
#pragma pack(1) //让编译器对这个结构作1字节对齐
struct test
{
char x1;
short x2;
float x3;
char x4;
};
#pragma pack() //取消1字节对齐,恢复为默认4字节对齐
这时候sizeof(struct test)的值为8。
变量声明和定义的区别:
变量声明只是变量的说明,在程序中不需要为其分配内存空间;而变量定义是为变量分配内存空间并初始化
4.C语言编译后的内存分布
C语言编译后的内存分布通常包括以下几个部分:
1. 代码段(Text Segment):也称为只读代码段,存放程序的机器指令。在程序运行时,代码段是只读的,不允许修改。
2. 数据段(Data Segment):存放已初始化的全局变量和静态变量。在程序加载时,数据段的大小是固定的。
3. BSS段(Block Started by Symbol):存放未初始化的全局变量和静态变量。在程序加载时,BSS段的大小是固定的,但是实际上并不占用磁盘空间,只是在程序运行时根据需要分配内存。
4. 堆(Heap):用于动态分配内存。在程序运行时,可以通过函数如malloc()和free()来动态地分配和释放堆内存。
5. 栈(Stack):用于存放函数的局部变量、函数参数和函数调用的上下文信息。栈是一种后进先出(LIFO)的数据结构,每次函数调用时,会在栈上分配一块内存,函数返回时会释放这块内存。
6. 环境变量区域:存放环境变量的值。
7. 命令行参数区域:存放命令行参数的值
5.C语言内存分区,未定义的全局变存放在哪个区
bss段:未初始化或初始化未0的全局变量和静态变量,具体体现为 一个占位符,不占用.exe文件空间,其内容由操作系统初始化/清零
6.静态局部变量存储在静态区,那么静态区的创建和消失是在什么时候?
静态区是在程序运行时由操作系统分配的一块内存空间,它的创建和消失与程序的生命周期有关。静态局部变量在程序运行时只会被初始化一次,它们的内存空间会一直存在直到程序结束。因此,静态区的创建和消失是在程序启动时创建,在程序结束时销毁。
7.变量加入static以后在内存中存储位置的变化
当一个变量被声明为static时,它的存储位置会从栈(stack)或堆(heap)转移到静态存储区(static storage area),也称为全局数据区(global data area)。
在栈或堆中声明的变量是在函数调用时动态分配的,当函数返回时,它们的存储空间会被释放。而在静态存储区中声明的变量则在程序运行期间一直存在,直到程序结束才会被释放。
因此,使用static声明的变量可以在多个函数之间共享,而不需要通过参数传递或全局变量来实现。此外,静态变量的初始值只会被赋值一次,即使函数被多次调用,它的值也会保持不变。
8.在windows里面运行了多个进程,其中一个进程执行完了,它的静态区会如何处理
当一个进程执行完毕后,操作系统会回收该进程的资源,包括其地址空间。在回收过程中,操作系统会释放该进程所占用的内存空间,包括静态区。释放静态区的具体处理方式取决于操作系统的实现。
一般情况下,操作系统会将静态区的内存空间标记为可用,以便其他进程可以重新使用。但是,静态区中的数据并不会立即被清除,而是等待下一个进程使用该内存空间时进行覆盖。因此,在下一个进程使用该静态区之前,原来进程的数据可能仍然存在于内存中。
9.连续调用同一个函数两次,它的局部变量初始化结果是否会一致?
一般情况下,连续调用同一个函数两次,它的局部变量初始化结果不会一致。这是因为每次函数调用时,局部变量都会重新初始化。如果函数中的局部变量没有被显式地初始化,那么它们的值将是未定义的,可能会导致不同的结果。但是,如果函数中的局部变量被显式地初始化为相同的值,那么它们的值将是一致的。
10.静态局部变量与局部变量的区别?为什么局部变量未定义时,每次初始化的结果是不确定的?是个真随机数还是个伪随机数?
静态局部变量和局部变量的区别在于它们的生命周期和作用域不同。静态局部变量在函数内部定义,但是它们的生命周期是整个程序运行期间,而不是函数调用期间。而局部变量的生命周期只在函数调用期间存在。
当局部变量未定义时,每次初始化的结果是不确定的。这是因为未初始化的局部变量的值是未定义的,它们的值取决于它们在内存中的位置和之前存储在该位置的值。因此,每次初始化的结果可能是不同的。
这些值通常是伪随机数,而不是真随机数。伪随机数是通过算法生成的数字序列,看起来像是随机的,但实际上是可预测的。在C语言中,未初始化的局部变量通常会被分配为内存中的随机值,这些值通常是伪随机数。
11.快排时间复杂度怎么计算的
快速排序的时间复杂度可以通过递归树来计算。在最坏情况下,每次划分都只能将序列分成一个元素和n-1个元素,这样递归树的深度就是n,每层的时间复杂度都是O(n),因此最坏情况下的时间复杂度是O(n^2)。
在平均情况下,每次划分都能将序列分成大小大致相等的两个子序列,递归树的深度是logn,每层的时间复杂度都是O(n),因此平均情况下的时间复杂度是O(nlogn)。
最好情况下,每次划分都能将序列分成大小相等的两个子序列,递归树的深度是logn,每层的时间复杂度都是O(n),因此最好情况下的时间复杂度也是O(nlogn)。
因此,快速排序的时间复杂度在最坏情况下是O(n^2),在平均情况下和最好情况下都是O(nlogn)。
12.用熟悉的编译器手写栈和冒泡排序
#define MAX_SIZE 100typedef struct {int data[MAX_SIZE];int top;
} Stack;// 初始化栈
void initStack(Stack *stack) {stack->top = -1;
}// 判断栈是否为空
int isEmpty(Stack *stack) {return stack->top == -1;
}// 判断栈是否已满
int isFull(Stack *stack) {return stack->top == MAX_SIZE - 1;
}// 入栈
void push(Stack *stack, int value) {if (isFull(stack)) {printf("Stack is full. Cannot push element.
");return;}stack->data[++stack->top] = value;
}// 出栈
int pop(Stack *stack) {if (isEmpty(stack)) {printf("Stack is empty. Cannot pop element.
");return -1;}return stack->data[stack->top--];
}// 获取栈顶元素
int peek(Stack *stack) {if (isEmpty(stack)) {printf("Stack is empty. Cannot peek element.
");return -1;}return stack->data[stack->top];
}int main() {Stack stack;initStack(&stack);push(&stack, 1);push(&stack, 2);push(&stack, 3);printf("Top element: %d
", peek(&stack));printf("Popped element: %d
", pop(&stack));printf("Popped element: %d
", pop(&stack));printf("Top element: %d
", peek(&stack));return 0;
}
void bubble_sort(int arr[], int n) {int i, j, temp;for (i = 0; i < n - 1; i++) {for (j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}int main() {int arr[] = {5, 2, 8, 3, 1, 6};int n = sizeof(arr) / sizeof(arr[0]);int i;printf("Before sorting: ");for (i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("
");bubble_sort(arr, n);printf("After sorting: ");for (i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("
");return 0;
}
相关文章:
嵌入式面试2(c相关)
目录 1.C语言中static、const、volatile关键字用法区别; static的用法(定义和用途) const的用法(定义和用途) volatile (英文意思为易变的) 作用和用法: 2.C语言中,const 和 static 的区别,c…...

基于SSM的n省出口基地公共信息服务平台设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...

opencv dnn模块 示例(20) 目标检测 object_detection 之 yolor
文章目录 1、论文介绍1.1、YOLOR思想动机1.2、隐式知识学习1.2.1、隐式知识如何工作1.2.2、隐式知识统一网络建模 1.3、实验1.4、总结 2、测试2.1、opencv dnn2.1.1、代码2.1.2、结果 2.2、测试效率 YOLOR出自论文You Only Learn One Representation: Unified Network for Mult…...

【队列的顺序表示,链式表示】
文章目录 队列的表示和实现相关术语队列的表示链队的表示链队的定义链队的初始化销毁链队列 链队列的入队出栈 队列的表示和实现 相关术语 队列(Queue)是仅在表尾进行插入操作,在表头进行删除操作的线性表。表尾即an端,称为队尾…...
Pydantic 实践
1. 简介 pydantic 库是一种常用的用于数据接口 schema 定义与检查的库。 通过 pydantic 库,我们可以更为规范地定义和使用数据接口,这对于大型项目的开发将会更为友好。 当然,除了 pydantic 库之外,像是 valideer 库、marshmallo…...
获取pandas中的众数
pandas.DataFrame 也有一个 mode() 方法。 以下面的 pandas.DataFrame 为例。 df pd.DataFrame({‘col1’: [‘X’, ‘X’, ‘Y’, ‘X’], ‘col2’: [‘X’, ‘Y’, ‘Y’, ‘X’]}, index[‘row1’, ‘row2’, ‘row3’, ‘row4’]) print(df) col1 col2 row1 X X row2…...

SOLIDWORKS Simulation2024仿真10大新功能
SOLIDWORKS Simulation新增功能 1. 增强型轴承接头 •通过指定压缩、拉伸和弯曲的刚度,轻松创建自定义轴承接头。•通过向非线性和大型位移算例添加自定义条件,提高模拟精度。 优点:使用功能强大的接口,更轻松 、 更 准 确 地 设…...
Java程序设计2023-第二次上机练习
这里要用到一些面向对象的基本知识 目录 7-1 伪随机数 输入格式: 输出格式: 输入样例: 输出样例: 7-2 jmu-Java-03面向对象基础-01-构造方法与toString 1.编写无参构造函数: 2.编写有参构造函数 3.覆盖toString函数: 4.对每个属性生成setter…...
如何在 uniapp 里面使用 pinia 数据持久化 (pinia-plugin-persistedstate)
想要在 uniapp 里面使用 pinia-plugin-persistedstate 会遇到的问题就是 uniapp里面没有浏览器里面的 sessionStorage localStorage 这些 api。 我们只需要替换掉 pinia-plugin-persistedstate 默认的储存 api 就可以了。使用 createPersistedState 重新创建一个实例, 把里面的…...

智慧矿山AI算法助力护帮板支护监测,提升安全与效率
在智慧矿山AI算法系列中,护帮板支护监测是保障矿山安全和提高生产效率的重要环节。护帮板作为矿山支护体系中的重要组成部分,在矿山生产中起到了关键的作用。那么,护帮板在哪种状态下是正常打开的呢?本文将对此进行介绍。 护帮板的…...

shell中的运算
目录 1.运算符号 2.运算指令 练习 1.运算符号 运算符号意义加法-减法*乘法/除法%除法后的余数**乘方自加一- -自减一<小于<小于等于>大于>大于等于等于ji ->jji*j*i->jj*i/j/i->jj/i%j%i->jj%i 2.运算指令 (()) //((a12))let //let a12 …...

【Java 进阶篇】解决Java Web应用中请求参数中文乱码问题
在Java Web应用开发中,处理请求参数时经常会遇到中文乱码的问题。当浏览器向服务器发送包含中文字符的请求参数时,如果不正确处理,可能会导致乱码问题,使得参数无法正确解析和显示。本文将详细探讨Java Web应用中请求参数中文乱码…...

51单片机-点阵屏led
代码配置 这样就能选择每一列哪个亮了 进行位选,段清零,这样就不会影响多列同时了 实现动画 1、使用文字摸提取文件,提取图案的16进制表示数组 offest作为偏移量,count作为计时。count10,偏移量加1,就相当于得到下一…...

Angular-03:组件模板
各种学习后的知识点整理归纳,非原创! 组件模板 ① 数据绑定② 属性绑定③ 类名绑定④ 样式绑定⑤ 事件绑定⑥ 获取原生DOM对象6.1 在组件模板中获取6.2 在组件类中获取 ⑦ 双向数据绑定⑧ 内容投影8.1 select选择器8.2 单槽投影8.3 多槽投影 ⑨ 安全操作…...
mysql 操作慢查询日志
1、mysql 批量插入300w数据 CREATE PROCEDURE test_insert_200w() BEGINDECLARE i INT;SET i1;WHILE i<3000000 DOINSERT INTO shop_user (password, telephone, username) VALUES (admin, 15510304125, concat(admin, i));SET ii1;END WHILE; END; //执行sql call test_in…...
illuminate/database 使用 二
上一篇文章写怎么单独使用illuminate/database,这回讲下怎么整合到项目里使用。为此特意看了下laravel对其使用。本篇文章,参照laravel的使用,简单实现。 一 原理 laravel 里使用illuminate/config。 illuminate/config composer 地址&…...

二叉树的概念
文章目录 二叉树一、树的概念1.树形结构1.1. 树的特点:1.2 概念:1.3 树的表示形式 2.树的应用 二、二叉树1.二叉数的概念2.满二叉树3.完全二叉树4.二叉树的性质练习: 二叉树 一、树的概念 1.树形结构 1.1. 树的特点: 1.根节点没…...

SpringCloud之Eureka的学习【详细】
目录 服务架构演变 单体架构 分布式架构 分布式架构需要考虑的问题 微服务 架构比较 微服务技术对比 服务拆分注意事项 案例 服务远程调用 RestTemplate Eureka注册中心 RestTemplate存在的问题 服务调用考虑的问题 Eureka的作用 搭建EurekaServer 服务注册 …...

学习ftp
文章目录 一、FTP介绍二、两种模式(主动模式和被动模式)三、FTP配置文件详解四、实际场景举例五、黑白名单六、网络限制 一、FTP介绍 1.FTP(File Transfer Protocol)是一种应用广泛且古老的互联网文件传输协议。 2.主要应用于互联…...

Android笔记(九):Compose组件的状态(一)
在使用Compose定义UI界面时,可以发现界面的变换往往与Compose组件内部的状态相关,当状态值发生变化时,Compose构成的可组合的界面也会刷新发生相应的变化。将在本笔记中将对可组合项的状态的定义、状态提升、状态丢失和状态的保存进行简单介绍…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...