嵌入式大佬 | 嵌入式C語言知識(shí)點(diǎn)萬字總結(jié)
1 關(guān)鍵字
嵌入式的應(yīng)用從邏輯上可以抽象為三個(gè)部分:
2). 數(shù)據(jù)的處理(如協(xié)議的解碼和封包,AD采樣值的轉(zhuǎn)換等)
3). 數(shù)據(jù)的輸出(GUI的顯示,輸出的引腳狀態(tài),DA的輸出控制電壓,PWM波的占空比等),
2 數(shù)據(jù)類型
typedef
unsigned
char
uint8_t;
typedef
unsigned
short
uint16_t;
typedef
unsigned
int
uint32_t;
......
typedef
signed
int
int32_t;
printf(
"int size:%d, short size:%d, char size:%d\n",
sizeof(
int),
sizeof(
char),
sizeof(
short));
char *p;
printf(
"point p size:%d\n",
sizeof(p));
3 內(nèi)存管理和存儲(chǔ)架構(gòu)
這里先看個(gè)簡單的C語言實(shí)例。
//main.c#include <stdio.h>#include <stdlib.h>
static
int st_val;
//靜態(tài)全局變量 -- 靜態(tài)存儲(chǔ)區(qū)
int ex_val;
//全局變量 -- 靜態(tài)存儲(chǔ)區(qū)int main(void)
{
int a =
0;
//局部變量 -- 棧上申請(qǐng)
int *ptr =
NULL;
//指針變量
static
int local_st_val =
0;
//靜態(tài)變量
local_st_val +=
1;
a = local_st_val;
ptr = (
int *)
malloc(
sizeof(
int));
//從堆上申請(qǐng)空間
if(ptr !=
NULL)
{
printf(
"*p value:%d", *ptr);
free(ptr);
ptr =
NULL;
//free后需要將ptr置空,否則會(huì)導(dǎo)致后續(xù)ptr的校驗(yàn)失效,出現(xiàn)野指針
}
}
LD_ROM
0x00800000
0x10000 { ;load region size_region
EX_ROM
0x00800000
0x10000 { ;load address = execution address
*.o (RESET, +First)
*(InRoot$Sections)
.ANY (+RO)
}
EX_RAM
0x20000000
0xC000 { ;rw Data
.ANY (+RW +ZI)
}
EX_RAM1
0x2000C000
0x2000 {
.ANY(MySection)
}
EX_RAM2
0x40000000
0x20000{
.ANY(Sdram)
}
}
int a[
10] __attribute__((section(
"Mysection")));
int b[
100] __attribute__((section(
"Sdram")));
4 指針和數(shù)組
int main(void)
{
char cval[] =
"hello";
int i;
int ival[] = {
1,
2,
3,
4};
int arr_val[][
2] = {{1, 2}, {3, 4}};
const
char *pconst =
"hello";
char *p;
int *pi;
int *pa;
int **par;
p = cval;
p++;
//addr增加1
pi = ival;
pi+=
1;
//addr增加4
pa = arr_val[
0];
pa+=
1;
//addr增加4
par = arr_val;
par++;
//addr增加8
for(i=
0; i<
sizeof(cval); i++)
{
printf(
"%d ", cval[i]);
}
printf(
"\n");
printf(
"pconst:%s\n", pconst);
printf(
"addr:%d, %d\n", cval, p);
printf(
"addr:%d, %d\n", icval, pi);
printf(
"addr:%d, %d\n", arr_val, pa);
printf(
"addr:%d, %d\n", arr_val, par);
}
/* PC端64位系統(tǒng)下運(yùn)行結(jié)果
0x68 0x65 0x6c 0x6c 0x6f 0x0
pconst:hello
addr:6421994, 6421995
addr:6421968, 6421972
addr:6421936, 6421940
addr:6421936, 6421944 */
#include <stdio.h>
typedef
struct
{
int b;
int a;
}STRUCT_VAL;
static __align(
4)
char arr[
8] = {
0x12,
0x23,
0x34,
0x45,
0x56,
0x12,
0x24,
0x53};
int main(void)
{
STRUCT_VAL *pval;
int *ptr;
pval = (STRUCT_VAL *)arr;
ptr = (
int *)&arr[
4];
printf(
"val:%d, %d", pval->a, pval->b);
printf(
"val:%d,", *ptr);
}
//0x45342312 0x53241256
//0x53241256
#include <stdio.h>
typedef int (*pfunc)(int, int);
int func_add(int a, int b){
return a+b;
}
int main(void)
{
pfunc *func_ptr;
*(
volatile
uint32_t *)
0x20001000 =
0x01a23131;
func_ptr = func_add;
printf(
"%d\n", func_ptr(
1,
2));
}
2)一個(gè)中斷服務(wù)子程序中會(huì)訪問到的非自動(dòng)變量(Non-automatic variables)
3)多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量
5 結(jié)構(gòu)類型和對(duì)齊
typedef
enum {spring=
1, summer, autumn, winter }season;
season s1 = summer;
typedef
union{
char c;
short s;
int i;
}UNION_VAL;
UNION_VAL val;
int main(void)
{
printf(
"addr:0x%x, 0x%x, 0x%x\n",
(
int)(&(val.c)), (
int)(&(val.s)), (
int)(&(val.i)));
val.i =
0x12345678;
if(val.s ==
0x5678)
printf(
"小端模式\n");
else
printf(
"大端模式\n");
}
/*
addr:0x407970, 0x407970, 0x407970
小端模式
*/
int data =
0x12345678;
short *pdata = (
short *)&data;
if(*pdata =
0x5678)
printf(
"%s\n",
"小端模式");
else
printf(
"%s\n",
"大端模式");
typedef int (*pfunc)(int, int);
typedef
struct{
int num;
int profit;
pfunc get_total;
}STRUCT_VAL;
int GetTotalProfit(int a, int b)
{
return a*b;
}
int main(void){
STRUCT_VAL Val;
STRUCT_VAL *pVal;
Val.get_total = GetTotalProfit;
Val.num =
1;
Val.profit =
10;
printf(
"Total:%d\n", Val.get_total(Val.num, Val.profit));
//變量訪問
pVal = &Val;
printf(
"Total:%d\n", pVal->get_total(pVal->num, pVal->profit));
//指針訪問
}
/*
Total:10
Total:10
*/
typedef
unsigned
char
uint8_t;
union reg{
struct{
uint8_t bit0:
1;
uint8_t bit1:
1;
uint8_t bit2_6:
5;
uint8_t bit7:
1;
}bit;
uint8_t all;
};
int main(void)
{
union reg RegData;
RegData.all =
0;
RegData.bit.bit0 =
1;
RegData.bit.bit7 =
1;
printf(
"0x%x\n", RegData.all);
RegData.bit.bit2_6 =
0x3;
printf(
"0x%x\n", RegData.all);
}
/*
0x81
0x8d
*/
數(shù)組 :按照基本數(shù)據(jù)類型對(duì)齊,第一個(gè)對(duì)齊了后面的自然也就對(duì)齊了。
聯(lián)合體 :按其包含的長度最大的數(shù)據(jù)類型對(duì)齊。
結(jié)構(gòu)體:結(jié)構(gòu)體中每個(gè)數(shù)據(jù)類型都要對(duì)齊,結(jié)構(gòu)體本身以內(nèi)部最大數(shù)據(jù)類型長度對(duì)齊
union DATA{
int a;
char b;
};
struct BUFFER0{
union DATA data;
char a;
//reserved[3]
int b;
short s;
//reserved[2]
};
//16字節(jié)
struct BUFFER1{
char a;
//reserved[0]
short s;
union DATA data;
int b;
};
//12字節(jié)
int main(void)
{
struct BUFFER0 buf0;
struct BUFFER1 buf1;
printf(
"size:%d, %d\n",
sizeof(buf0),
sizeof(buf1));
printf(
"addr:0x%x, 0x%x, 0x%x, 0x%x\n",
(
int)&(buf0.data), (
int)&(buf0.a), (
int)&(buf0.b), (
int)&(buf0.s));
printf(
"addr:0x%x, 0x%x, 0x%x, 0x%x\n",
(
int)&(buf1.a), (
int)&(buf1.s), (
int)&(buf1.data), (
int)&(buf1.b));
}
/*
size:16, 12
addr:0x61fe10, 0x61fe14, 0x61fe18, 0x61fe1c
addr:0x61fe04, 0x61fe06, 0x61fe08, 0x61fe0c
*/
6 預(yù)處理機(jī)制
include 包含文件命令,在C語言中,它執(zhí)行的效果是將包含文件中的所有內(nèi)容插入到當(dāng)前位置,這不只包含頭文件,一些參數(shù)文件,配置文件,也可以使用該文件插入到當(dāng)前代碼的指定位置。其中<>和""分別表示從標(biāo)準(zhǔn)庫路徑還是用戶自定義路徑開始檢索。
define宏定義,常見的用法包含定義常量或者代碼段別名,當(dāng)然某些情況下配合##格式化字符串,可以實(shí)現(xiàn)接口的統(tǒng)一化處理,實(shí)例如下:
#define MAX_SIZE 10
#define MODULE_ON 1
#define ERROR_LOOP() do{\
printf("error loop\n");\
}while(0);
#define global(val) g_##val
int global(v) =
10;
int global(add)(int a, int b)
{
return a+b;
}
if..#elif…#else…#endif, #ifdef..#endif, #ifndef…#endif條件選擇判斷,條件選擇主要用于切換代碼塊,這種綜合性項(xiàng)目和跨平臺(tái)項(xiàng)目中為了滿足多種情況下的需求往往會(huì)被使用。
undef 取消定義的參數(shù),避免重定義問題。
error,#warning用于用戶自定義的告警信息,配合#if,#ifdef使用,可以限制錯(cuò)誤的預(yù)定義配置。
pragma 帶參數(shù)的預(yù)定義處理,常見的#pragma pack(1), 不過使用后會(huì)導(dǎo)致后續(xù)的整個(gè)文件都以設(shè)置的字節(jié)對(duì)齊,配合push和pop可以解決這種問題,代碼如下:
#pragma pack(push)
#pragma pack(1)
struct TestA
{
char i;
int b;
}A;
#pragma pack(pop); //注意要調(diào)用pop,否則會(huì)導(dǎo)致后續(xù)文件都以pack定義值對(duì)齊,執(zhí)行不符合預(yù)期
等同于
struct _TestB{
char i;
int b;
}__attribute__((packed))A;
總結(jié)
猜你喜歡(點(diǎn)擊下劃線即可跳轉(zhuǎn)閱讀
嵌入式牛人 | 這些單片機(jī)編程思想超硬核
嵌入式必會(huì)!C語言最常用的貪心算法就這么被攻略了
Linux!為何他一人就寫出這么強(qiáng)的系統(tǒng)?
最 后
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請(qǐng)聯(lián)系我們,謝謝!





