【面試筆記】嵌入式軟件工程師,汽車電子軟件相關

在這里插入圖片描述

文章目錄

  • 1. C語言基礎
    • 1.1 const
    • 1.2 static
    • 1.3 回調函數的用法
    • 1.4 宏定義
    • 1.5 編譯、鏈接過程
    • 1.6 堆與棧的區別?
    • 1.7 簡單的字符串算法題,C語言實現
      • 1.7.1 給定一個字符串,按順序篩選出不重復的字符組成字符串,輸出該字符串
      • 1.7.2 給定4*4矩陣,回文打印輸出
    • 1.8 字節對其
  • 2. MCU相關
    • 2.1 MCU的啟動過程描述
    • 2.2 MCU的內存布局
    • 2.3 使用volatile關鍵字的作用?
  • 3. 汽車電子軟件
    • 3.1 CAN/CANFD相關
      • 3.1 概述一個CAN消息如何被發送和接收的
      • 3.2 CAN和FIFO CAN
      • 3.3 CANFD的知識點
    • 3.2 概述bootloader實現要點
      • 3.2.1 跳轉前要做什么?
    • 3.3 簡述ASPICE在項目研發中的應用
    • 3.4 舉例說明某個功能安全需求的實現過程
    • 3.5 概述14229協議
    • 3.6 概述15765協議


1. C語言基礎

1.1 const

修飾變量
只可訪問,不可重新賦值。

const int MAX_VALUE = 100;void printValue(const int value);

修飾指針

  • 限制指向位置
const int *ptr;
  • 限制指向數據
const int *const ptr;

1.2 static

靜態變量
使用 static 關鍵字聲明靜態變量時,變量的生命周期會延長到整個程序運行期間,而不僅僅局限在其定義的作用域內。靜態變量在第一次被賦值時初始化,并且保留其值直到程序結束。

靜態全局變量
使用 static 關鍵字在全局作用域中聲明的變量具有靜態存儲持續時間,但是其作用域被限制在聲明該變量的源文件內。這使得該變量對其他源文件不可見,可以防止命名沖突。

靜態函數
使用 static 關鍵字聲明靜態函數時,該函數僅在聲明所在的源文件中可見,即它具有內部鏈接性。靜態函數的作用域僅限于聲明所在的源文件。這種方式可以避免與其他源文件中的同名函數產生沖突。


1.3 回調函數的用法

用于在函數執行過程中調用另一個函數。回調函數允許我們向一個函數傳遞另一個函數的地址,從而在需要時執行特定的操作。回調函數通常用于事件處理、異步編程、庫函數的擴展等場景。

  1. 定義回調函數
    首先定義一個函數作為回調函數,其函數原型應與回調的要求相匹配。例如:
void callbackFunction(int result) {printf("Callback result: %d\n", result);
}
  1. 在函數中注冊回調函數
    在需要的地方將回調函數注冊進目標函數中,通常通過函數指針實現。例如:
void performOperation(void (*callback)(int)) {int result = 100; // 模擬操作結果// 執行操作...// 調用回調函數callback(result);
}
  1. 調用包含回調函數的函數
    最后調用包含回調函數的函數,將回調函數的地址傳遞給要調用的函數。例如:
int main() {performOperation(callbackFunction); // 注冊回調函數return 0;
}

在這個示例中,performOperation 函數執行某個操作后調用了注冊的回調函數 callbackFunction,并將結果傳遞給回調函數進行處理。

通過回調函數,我們可以實現靈活的程序設計,允許函數根據不同情況來調用不同的操作,增加了程序的可擴展性和可重用性。當需要在函數執行過程中動態切換功能時,回調函數是一個非常有用的工具。

使用回調函數有以下一些好處:

  1. 靈活性和可擴展性
    回調函數提供了一種靈活的機制,使得代碼可以在不同的場景中進行定制和擴展。通過將特定的功能封裝在回調函數中,可以根據需要動態地更改或添加行為,而無需修改主函數的邏輯。
  2. 解耦和模塊化
    回調函數有助于將不同的功能模塊分離,使代碼更具有模塊化和可維護性。主函數可以專注于其核心邏輯,而將特定的任務委托給回調函數來處理。這樣可以提高代碼的可讀性和可重用性。
  3. 異步處理和事件驅動
    回調函數常用于異步操作或事件驅動的場景中。例如,在異步 I/O 操作完成或特定事件發生時,可以通過回調函數來處理相應的邏輯。這有助于提高程序的并發性和響應性。
  4. 定制性和擴展性
    回調函數允許用戶提供自己的自定義邏輯,以滿足特定的需求。這使得程序可以更好地適應各種不同的用例和業務邏輯。
  5. 代碼復用
    回調函數可以作為可復用的模塊,在多個地方被調用,從而減少代碼冗余。

需要注意的是,在使用回調函數時,要確保正確處理回調函數的參數和返回值,并注意線程安全等問題。合理使用回調函數可以提高代碼的靈活性和擴展性,但也需要謹慎設計和管理,以避免引入復雜度過高或難以調試的問題。


1.4 宏定義

在 C 語言中,宏定義是一種預處理器指令,用于在編譯階段進行文本替換。它允許你定義一個標識符(通常是一個宏名),并將其與一個特定的文本表達式或代碼塊關聯起來。當在代碼中使用該宏名時,編譯器會將其替換為相應的文本。
宏定義的常見用法和好處包括:

  1. 常量定義
    使用宏定義可以創建常量,例如定義一些具有特定值的常量,以增強代碼的可讀性和可維護性。
  2. 代碼簡化和抽象
    宏定義可以用于簡化復雜的表達式或代碼塊,使其更易于閱讀和理解。例如,將常用的計算或操作封裝在宏中,以便在多個地方重復使用。
  3. 條件編譯
    通過宏定義可以實現條件編譯,根據不同的條件編譯不同的代碼塊。這對于處理不同平臺、版本或配置的情況非常有用。
  4. 代碼移植性
    宏定義可以幫助提高代碼的可移植性。例如,可以使用宏來定義平臺特定的代碼或處理不同編譯器的差異。
  5. 提高性能
    在一些情況下,宏定義可以提供一定的性能優勢,特別是對于一些簡單的計算或操作。
    例如,以下是一個簡單的宏定義示例:
#define MAX_SIZE 100

在上面的示例中,MAX_SIZE 是一個宏名,100 是它關聯的文本。在代碼中使用 MAX_SIZE 時,它將被替換為 100。
需要注意的是,宏定義也有一些潛在的問題和限制:

  1. 宏展開問題
    宏在編譯時會進行文本替換,可能會導致一些意外的副作用,例如嵌套宏展開、參數求值順序等問題。
  2. 缺乏類型檢查
    宏不進行類型檢查,可能會導致在使用時出現類型不匹配或其他錯誤。
  3. 可讀性問題
    過度使用宏可能會使代碼變得難以理解,特別是當宏的定義和使用變得復雜時。

因此,在使用宏定義時,應該謹慎考慮,并確保其使用不會導致代碼的可讀性和可維護性下降。在一些情況下,使用函數或其他語言特性可能是更好的選擇。


1.5 編譯、鏈接過程

在這里插入圖片描述
預處理
根據以字符#開頭的命令修飾的main.c的C源文件,生成預處理后的C源文件 main.i。
該過程主要進行文本替換、宏展開、刪除注釋等工作。
對應的gcc命令:

gcc -E main.c main.i

編譯
編譯器將文本文件main.i翻譯(編譯)成匯編文件main.s
對應的gcc命令:

gcc -S main.i mian.s

匯編
編譯器將main.s翻譯成機器語言指令,并把這些指令打包成一種可重定位目標程序的格式,并將結果保存在目標文件main.o中

把一個源文件翻譯成目標程序的工作過程分為五個階段:詞法分析、語法分析、語義檢查和中間代碼生成。主要是進行詞法分析和語法分析,又稱為源程序分析,分析過程中發現語法錯誤并給出提示信息。
對應的gcc命令:

gcc -c main.s mian.o

鏈接
該過程編譯器將靜態庫和動態庫的庫函數鏈接到可執行程序中。
靜態庫是指編譯鏈接時,把庫文件的代碼全部加入到可執行文件中,因此生成的文件比較大,但在運行時就不在需要庫文件了,其后綴一般為.a。
動態庫則是在程序運行時被鏈接加載,這樣可以節省系統的開銷,其后綴一般為.so,gcc在編譯時默認使用動態庫。


1.6 堆與棧的區別?

請添加圖片描述

  1. 棧空間是系統自動分配和回收,堆的空間是用戶手動分配回收的;
  2. 棧空間較小,堆空間較大;
  3. 棧的地址空間向下生長,堆則向上生長;
  4. 棧的存儲效率更高。
    參考:棧和堆,以STM32為例說明

1.7 簡單的字符串算法題,C語言實現

1.7.1 給定一個字符串,按順序篩選出不重復的字符組成字符串,輸出該字符串

參考示例:

#include <stdio.h>
#include <string.h>void removeDuplicates(char *str) {int len = strlen(str);if (len < 2) return;int tail = 1;for (int i = 1; i < len; ++i) {int j;for (j = 0; j < tail; ++j) {if (str[i] == str[j]) break;}if (j == tail) {str[tail] = str[i];++tail;}}str[tail] = '\0'; //此處是關鍵
}int main() {char str[100];printf("Enter a string: ");scanf("%s", str);removeDuplicates(str);printf("String with duplicates removed: %s\n", str);return 0;
}

測試結果:

Enter a string: asbdssjikSNjs78137!@#ssa00smk
String with duplicates removed: asbdjikSN7813!@#0m

1.7.2 給定4*4矩陣,回文打印輸出

參考示例:

#include <stdio.h>#define ROWS 4
#define COLS 4void printClockwise(int matrix[ROWS][COLS]) {int top = 0, bottom = ROWS - 1, left = 0, right = COLS - 1;while (top <= bottom && left <= right) {// Print top rowfor (int i = left; i <= right; ++i)printf("%d ", matrix[top][i]);top++;// Print right columnfor (int i = top; i <= bottom; ++i)printf("%d ", matrix[i][right]);right--;// Print bottom rowif (top <= bottom) {for (int i = right; i >= left; --i)printf("%d ", matrix[bottom][i]);bottom--;}// Print left columnif (left <= right) {for (int i = bottom; i >= top; --i)printf("%d ", matrix[i][left]);left++;}}
}int main() {int matrix[ROWS][COLS] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 16}};printf("Clockwise printing of the matrix:\n");printClockwise(matrix);return 0;
}

測試結果:

Clockwise printing of the matrix:
1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

參考:算法11:順時針轉圈打印矩陣


1.8 字節對其

問題】32位系統,一個結構體中,成員依次是char、short、int、char類型,問這個結構體總共占多少字節?
回答這個問題需要深刻理解結構體所占空間的分布:

|char |-----|short|short|4字節
|int  |int  |int  |int  |4字節
|char |-----|-----|-----|4字節

所以,該結構體共占12字節

測試代碼:

#include <stdio.h>struct TMP{char a;short b;int c;char d;
};int main(void) {printf("size = %d", sizeof(struct TMP));return 0;
}

總結:

  • 結構體成員占位是其自身類型長度的整數倍
  • 結構體整體需要對齊,目標對齊長度的整數倍

2. MCU相關

2.1 MCU的啟動過程描述

參考STM32的啟動過程 — startup_xxxx.s文件解析(MDK和GCC雙環境)


2.2 MCU的內存布局

在這里插入圖片描述
在這里插入圖片描述

參考:

  1. 內存布局:深度剖析應用程序中的內存布局
  2. stm32的內存分布

2.3 使用volatile關鍵字的作用?

  1. 硬件寄存器操作
    單片機通常與硬件設備交互,硬件寄存器的值可能會在硬件事件的觸發下發生改變。通過將訪問硬件寄存器的變量聲明為 volatile,可以告訴編譯器不要對該變量進行優化,以確保每次訪問都能獲取到最新的寄存器值。
  2. 共享變量
    在多線程或中斷處理程序中,多個執行路徑可能同時訪問和修改同一個變量。將這樣的共享變量聲明為 volatile,可以確保編譯器生成的代碼正確地處理變量的讀和寫,避免出現競態條件等問題。
  3. 中斷服務程序
    中斷服務程序可能會修改一些全局變量,而這些變量在主程序中也會被訪問。將這些變量聲明為 volatile,可以保證中斷服務程序對變量的修改能及時反映到主程序中。
  4. 實時性要求高的代碼
    在一些對實時性要求較高的場景中,使用 volatile 可以確保關鍵變量的訪問不會被編譯器優化掉,從而保證代碼的實時性。

通過使用 volatile,可以幫助編譯器生成更準確的代碼,避免一些由于變量的不確定性導致的問題。然而,具體的應用場景和使用方法可能會因單片機的類型、編譯器的特性以及項目的需求而有所不同。在實際編程中,還需要根據具體情況進行適當的測試和調試。


3. 汽車電子軟件

3.1 CAN/CANFD相關

3.1 概述一個CAN消息如何被發送和接收的

TBD.


3.2 CAN和FIFO CAN

TBD.


3.3 CANFD的知識點

TBD.


3.2 概述bootloader實現要點

3.2.1 跳轉前要做什么?

  • 禁止所有外設時鐘;
  • 禁止使用的 PLL;
  • 禁止所有中斷;
  • 清除所有中斷掛起標志。

3.3 簡述ASPICE在項目研發中的應用

TBD.


3.4 舉例說明某個功能安全需求的實現過程

TBD.


3.5 概述14229協議

TBD.


3.6 概述15765協議

TBD.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/22998.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/22998.shtml
英文地址,請注明出處:http://en.pswp.cn/web/22998.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python3 迭代器和生成器

前言 本文主要介紹Python中的迭代器和生成器&#xff0c;主要內容包括 迭代器概述、生成器簡介。 文章目錄 前言一、迭代器簡介二、生成器簡介 一、迭代器簡介 在 Python 中&#xff0c;迭代器(iterator)是一個實現了迭代器協議&#xff08;Iterator Protocol&#xff09;的…

opencv進階 ——(十一)基于RMBG實現生活照生成寸照

實現步驟 1、檢測人臉&#xff0c;可以使用opencv自帶的級聯分類器或者dlib實現人臉檢測 2、放大人臉范圍&#xff0c;調整到正常寸照尺寸 3、基于RMGB算法得到人像掩碼 4、生成尺寸相同的純色背景與當前人像進行ALPHA融合即可 alpha融合實現 void alphaBlend(cv::Mat&…

1 機器人軟件開發學習所需通用技術棧(一)

機器人軟件工程師技術路線&#xff08;如有缺失&#xff0c;歡迎補充&#xff09; 1. 機器人軟件開發工程師技術路線 1.1 基礎知識 C/C編程&#xff1a;掌握C/C語言基礎&#xff0c;包括數據結構、算法、內存管理等。操作系統&#xff1a;了解Linux或Windows等操作系統的基本…

android 13 aosp 預置so庫

展訊對應的main.mk配置 device/sprd/qogirn**/ums***/product/***_native/main.mk $(call inherit-product-if-exists, vendor/***/build.mk)vendor/***/build.mk PRODUCT_PACKAGES \libtestvendor///Android.bp cc_prebuilt_library_shared{name:"libtest",srcs:…

2.1 初識Windows程序

Windows程序設計是一種面向對象的編程。Windows操作系統以數據結構的形式定義了大量預定義的對象作為操作系統的數據類型。Windows動態鏈接庫提供了各種各樣的API接口函數供Windows應用程序調用。一個Windows應用程序是運行在Windows操作系統之上的。這些API接口函數的調用所實…

1349:【例4-10】最優布線問題

【解題思路】 最小生成樹模板題&#xff0c;求最小生成樹所有邊權加和。 該題輸入的是鄰接矩陣&#xff0c;因此使用鄰接矩陣解決該問題。當然也可以保存為鄰接表。 【參考代碼】 //示例代碼 Prim算法 #include <iostream> #include <cstring> #include <cs…

【Vue】路由的基本使用

文章目錄 一、固定5個固定的步驟二、代碼示例三、兩個核心步驟四、完整代碼 vue-router插件作用 修改地址欄路徑時&#xff0c;切換顯示匹配的組件 說明 Vue 官方的一個路由插件&#xff0c;是一個第三方包 官網 https://v3.router.vuejs.org/zh/ VueRouter的使用&#xff0…

TCP/IP協議介紹——三次握手四次揮手

TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff0c;傳輸控制協議/網際協議&#xff09;是指能夠在多個不同網絡間實現信息傳輸的協議簇。TCP/IP協議不僅僅指的是TCP 和IP兩個協議&#xff0c;而是指一個由FTP、SMTP、TCP、UDP、IP等協議構成的協議…

CSS學習|css三種導入方式、基本選擇器、層次選擇器、結構偽類選擇器、屬性選擇器、字體樣式、文本樣式

第一個css程序 css程序都是在style標簽中書寫 打開該網頁&#xff0c;可以看到h1標簽中的我是標題被渲染成了紅色 可以在同級目錄下創建一個css目錄&#xff0c;專門存放css文件&#xff0c;可以和html分開編寫 然后在html頁面中&#xff0c;利用link標簽以及css文件地址&…

大模型基架:Transformer如何做優化?

大模型的基礎模式是transformer&#xff0c;所以很多芯片都實現先專門的transformer引擎來加速模型訓練或者推理。本文將拆解Transformer的算子組成&#xff0c;展開具體的數據流分析&#xff0c;結合不同的芯片架構實現&#xff0c;分析如何做性能優化。 Transformer結構 tr…

go的反射和斷言

在go中對于一個變量&#xff0c;主要包含兩個信息變量類型&#xff08;type&#xff09;和變量值&#xff08;value&#xff09; 可以通過reflect包在運行的時候動態獲取變量信息&#xff0c;并能夠進行操作 對于Type可以通過reflect.TypeOf()獲取到變量的類型信息 reflect.Ty…

13_前端工程化_ES6

1.前端工程化概念 前端工程化是使用軟件工程的方法來單獨解決前端的開發流程中模塊化、組件化、規范化、自動化的問題,其主要目的為了提高效率和降低成本。 前后端分離&#xff08;前端代碼工程化獨立出來形成一個單獨的app&#xff09; 1.開發分離 2.部署分離 3.服務器分離…

信號(上)

本節目標&#xff1a; 1. 掌握Linux信號的基本概念 2. 掌握信號產生的一般方式 3. 理解信號遞達和阻塞的概念&#xff0c;原理。 4. 掌握信號捕捉的一般方式。 5. 重新了解可重入函數的概念。 6. 了解競態條件的情景和處理方式 7. 了解SIGCHLD信號&#xff0c; 重新編寫信號處理…

ChatGPT基本原理詳細解說

ChatGPT基本原理詳細解說 引言 在人工智能領域&#xff0c;自然語言處理&#xff08;NLP&#xff09;一直是研究的熱點之一。隨著技術的發展&#xff0c;我們見證了從簡單的聊天機器人到復雜的語言模型的演變。其中&#xff0c;ChatGPT作為一項突破性技術&#xff0c;以其強大…

【Vue】自定義指令-v-loading指令的封裝

場景 實際開發過程中&#xff0c;發送請求需要時間&#xff0c;在請求的數據未回來時&#xff0c;頁面會處于空白狀態 > 用戶體驗不好 需求 封裝一個 v-loading 指令&#xff0c;實現加載中的效果 分析 本質 loading效果就是一個蒙層&#xff0c;蓋在了盒子上 數據請求…

從零開始精通Onvif之設備發現

設備發現的意義 在復雜的網絡環境中&#xff0c;如何快速而準確地識別網絡上的Onvif設備&#xff0c;對于攝像頭廠商、系統集成商、開發人員乃至最終用戶來說&#xff0c;都顯得至關重要。 首先&#xff0c;設備發現有效簡化了集成的復雜度。在沒有統一標準之前&#xff0c;每個…

2004NOIP普及組真題 2. 花生采摘

線上OJ&#xff1a; 【04NOIP普及組】花生采摘 核心思想&#xff1a; 1、本題為貪心即可。 2、因為本題嚴格限制了順序&#xff0c;所以先把每個節點的花生數量按降序排序。然后逐一判斷下一個花生是否需要去采摘即可 3、每一次采摘完&#xff0c;記錄耗時 t 以及采集的花…

力扣第417題測試程序

題目描述&#xff1a; 有一個 m n 的矩形島嶼&#xff0c;與 太平洋 和 大西洋 相鄰。 “太平洋” 處于大陸的左邊界和上邊界&#xff0c;而 “大西洋” 處于大陸的右邊界和下邊界。 這個島被分割成一個由若干方形單元格組成的網格。給定一個 m x n 的整數矩陣 heights &#…

基于web的垃圾分類回收系統的設計

管理員賬戶功能包括&#xff1a;系統首頁&#xff0c;個人中心&#xff0c;管理員管理&#xff0c;用戶管理&#xff0c;公告管理&#xff0c;運輸管理&#xff0c;基礎數據管理 用戶賬戶功能包括&#xff1a;系統首頁&#xff0c;個人中心&#xff0c;運輸管理&#xff0c;公告…

pyqt QlineEdit內部增加按鈕方法

pyqt QlineEdit內部增加按鈕方法 def addButton(self,lineEdit):btn QtWidgets.QPushButton("")icon1 QtGui.QIcon()icon1.addPixmap(QtGui.QPixmap(":/image/images/th.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)btn.setIcon(icon1)btn.setStyleShe…