既然不同平台的基本数据宽度不同,那么如何确定当前平台的基础数据类型如int的宽度,这就需要C语言提供的接口sizeof,实现如下。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
", sizeof(int), sizeof(char), sizeof(short));
这里还有重要的知识点,就是指针的宽度,如
其实这就和芯片的可寻址宽度有关,如32位MCU的宽度就是4,64位MCU的宽度就是8,在有些时候这也是查看MCU位宽比较简单的方式。char *p;printf("point p size:%d ", sizeof(p));
C语言的作用域不仅描述了标识符的可访问的区域,其实也规定了变量的存储区域,在文件作用域的变量st_val和ex_val被分配到静态存储区,其中static关键字主要限定变量能否被其它文件访问,而代码块作用域中的变量a, ptr和local_st_val则要根据类型的不同,分配到不同的区域,其中a是局部变量,被分配到栈中,ptr作为指针,由malloc分配空间,因此定义在堆中,而local_st_val则被关键字限定,表示分配到静态存储区,这里就涉及到重要知识点,static在文件作用域和代码块作用域的意义是不同的:在文件作用域用于限定函数和变量的外部链接性(能否被其它文件访问), 在代码块作用域则用于将变量分配到静态存储区。//main.c#include #includestatic int st_val; //静态全局变量 -- 静态存储区int ex_val; //全局变量 -- 静态存储区int main(void){int a = 0; //局部变量 -- 栈上申请int *ptr = NULL; //指针变量static int local_st_val = 0; //静态变量local_st_val += 1;a = local_st_val;ptr = (int *)malloc(sizeof(int)); //从堆上申请空间if(ptr != NULL){printf("*p value:%d", *ptr);free(ptr);ptr = NULL;//free后需要将ptr置空,否则会导致后续ptr的校验失效,出现野指针}}
LD_ROM 0x00800000 0x10000 { ;load region size_regionEX_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")));采用这种方式,我们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增加8for(i=0; i(cval);> {printf("%d ", cval[i]); }printf(" ");printf("pconst:%s ", pconst);printf("addr:%d, %d ", cval, p);printf("addr:%d, %d ", icval, pi);printf("addr:%d, %d ", arr_val, pa);printf("addr:%d, %d ", arr_val, par);} /* PC端64位系统下运行结果0x68 0x65 0x6c 0x6c 0x6f 0x0pconst:helloaddr:6421994, 6421995addr:6421968, 6421972addr:6421936, 6421940addr:6421936, 6421944 */#include 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 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 ", func_ptr(1, 2));} 联合体的是能在同一个存储空间里存储不同类型数据的数据类型,对于联合体的占用空间,则是以其中占用空间最大的变量为准,如下: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 ", (int)(&(val.c)), (int)(&(val.s)), (int)(&(val.i))); val.i = 0x12345678; if(val.s == 0x5678) printf("小端模式 "); elseprintf("大端模式 "); } /*addr:0x407970, 0x407970, 0x407970 小端模式*/int data = 0x12345678; short *pdata = (short *)&data; if(*pdata = 0x5678) printf("%s ", "小端模式"); else printf("%s ", "大端模式");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 ", Val.get_total(Val.num, Val.profit)); //变量访问 pVal = &Val; printf("Total:%d ", 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 ", RegData.all); RegData.bit.bit2_6 = 0x3; printf("0x%x ", RegData.all); } /* 0x81 0x8d*/union DATA{ int a; char b; }; struct BUFFER0{union DATA data; char a; //reserved[3] int b; short s; //reserved[2] }; //16字节 struct BUFFER1{char a; //reserved[0] short s; union DATA data; int b; };//12字节 int main(void){ struct BUFFER0 buf0;struct BUFFER1 buf1;printf("size:%d, %d ", sizeof(buf0), sizeof(buf1)); printf("addr:0x%x, 0x%x, 0x%x, 0x%x ", (int)&(buf0.data), (int)&(buf0.a), (int)&(buf0.b), (int)&(buf0.s)); printf("addr:0x%x, 0x%x, 0x%x, 0x%x ", (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 */#define MAX_SIZE 10#define MODULE_ON 1#define ERROR_LOOP() do{ printf("error loop "); }while(0);#define global(val) g_##valint global(v) = 10;int global(add)(int a, int b){return a+b;}#if..#elif...#else...#endif, #ifdef..#endif, #ifndef...#endif#pragma pack(push)#pragma pack(1)struct TestA{char i;int b;}A;#pragma pack(pop); //注意要调用pop,否则会导致后续文件都以pack定义值对齐,执行不符合预期等同于struct _TestB{char i;int b; }__attribute__((packed))A;原文标题:长文 | 深度总结嵌入式C语言必学知识点
文章出处:【微信公众号:STM32嵌入式开发】欢迎添加关注!文章转载请注明出处。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !