【嵌入式C语言】09.程序编译过程+大小端+主函数传参+结构体+结构体内存对齐+联合+枚举+头文件

【嵌入式C语言】09.程序编译过程+大小端+主函数传参+结构体+结构体内存对齐+联合+枚举+头文件 一、程序编译的四个过程1.一步到位gcc hello.c -o hello //没有体现出程序编译的四个步骤2.预处理命令C语言预处理器提供了一系列的编译指令都是#开头的有三种,全部都是#开头第一种#include第二种#define第三种条件编译3.分步讲解hello.c --》hello第一步预处理(处理C程序中所有#开头的语句)把#开头的语句展开gcc hello.c -o hello.i -E //(-E 编译选项用来对程序进行预处理)第二步编译(把.i文件编译得到.s的汇编文件)gcc hello.i -o hello.s -S第三步汇编(.o文件叫做可重定位文件)gcc hello.s -o hello.o -c第四步链接生成最终的可执行程序gcc hello.o -o hello二、大小端(字节序)1.概念大小端用来描述计算机中数据的存储方式大端序数据的高字节存放到低地址低字节存放到高地址跟日常一样小端序数据的高字节存放到高地址低字节存放到低地址跟日常相反ubuntu采用小端序存放题目三、主函数传参1.C语言主函数的写法int main() //不带参数void main()int main(int argc,char **argv) //带参数写法一(二级指针写法int main(int argc,char *argv[]) //带参数写法二指针数组写法{}参数argc --》参数的个数,会把程序名也当成是参数比如: ./hello 123 456 参数有三个argv --》你传递过来的参数argv[0] -- ./hello——》第一个参数argv[1] -- 123——》第二个参数argv[2] -- 456——》第三个参数指针数组的数组名在绝大多数使用场景下会退化为二级指针类型2.特点和作用特点主函数传参传过去的默认都是字符串作用通过传递参数让主函数运行的时候可以接收外界的参数3.传参格式四、结构体1.结构体学生信息 --》用基本数据类型无法全面描述一个学生分散定义的不是一个整体结构体是程序员自定义的一种复合数据类型(可以把其它任何数据类型合并打包到结构体中形成一个整体)2.定义结构体struct 结构体的名字{你想要的各种数据类型};比如struct student{char name[10]; //姓名int age; //年龄float score; //分数};写法一typedef struct student{char name[10]; //姓名int age; //年龄float score; //分数}stu;写法二typedef struct student{char name[10]; //姓名int age; //年龄float score; //分数}stu,*stup;3.使用结构体写法一 struct student stu1{zhangsan,18,56.9};写法二 struct student stu1;strcpy(stu1.name,张三); //char数组不能直接赋值字符串stu1.age19;stu1.score85.5;写法三结构体变量之间可以直接赋值struct student stu2;//stu2stu1; //一句话就能搞定//等价于下面三句话strcpy(stu2.name,stu1.name);stu2.agestu1.age;stu2.scorestu1.score;普通结构体变量struct student stu1;调用结构体里面的成员,使用直接成员运算符.stu1.age19;stu1.score58.2;结构体指针struct student *stu1malloc(sizeof(struct student));调用结构体里面的成员,使用间接成员运算符-stu1-age19;stu1-score58.2;3.使用结构体写法一 struct student stu1{zhangsan,18,56.9};——》定义时初始化必须按顺序写法二 struct student stu1;——》定义时没初始化后面可以不按顺序赋值strcpy(stu1.name,张三); //char数组不能直接赋值字符串stu1.age19;stu1.score85.5;写法三结构体变量之间可以直接赋值struct student stu2;//stu2stu1; //一句话就能搞定//等价于下面三句话strcpy(stu2.name,stu1.name);stu2.agestu1.age;stu2.scorestu1.score;普通结构体变量struct student stu1;调用结构体里面的成员,使用直接成员运算符.stu1.age19;stu1.score58.2;结构体指针struct student *stu1malloc(sizeof(struct student));调用结构体里面的成员,使用间接成员运算符-stu1-age19;stu1-score58.2;4.结构体求大小sizeof(struct student); 鹏哥结构体内存对齐正确的规则结构体大小必须满足字节对齐第一步找到结构体类型最大的成员(如果是数组,看类型不是看整个数组)类型最大的成员大于等于8字节--》整个结构体按照8字节对齐类型最大的成员小于8字节--》整个结构体按照最大类型占用的字节数对齐第二步从上到下依次往地址中存放成员(为了方便大家计算我总结了方法就从0地址开始存放)存放的时候要求成员的首地址能够被成员类型大小整除总结方法:画图所有的结构体都从0地址开始存放,从上到下依次存放存放的过程中用当前地址值除以当前变量的类型大小,能整除就存放在这个位置,不能整除就往后空着5.结构体的嵌套struct book{char bookname[20];float bookprice;};struct student{struct book b1;char name[10];};struct student stu1; //定义了一个学生strcpy(stu1.name,王建国);stu1.b1.bookprice58.5;strcpy(stu1.b1.bookname,西游记);五、共用体(也叫做联合体)1.定义共用体union 共用体的名字{成员;};union sex{char man;char woman;};2.用法普通联合体变量 用小数点联合体指针 用-3.特点联合体中所有的成员公用同一块内存区域联合体的大小由最大的成员大小来决定也要满足字节对齐(最大类型对齐)六、枚举1.本质上就是整型常量enum color {red,green,blue,black}; //定义了枚举类型color枚举值分别是red,green,blue,black2.特点第一个枚举值没有人为赋值默认从0开始第二个枚举值如果人为赋值枚举值从你赋值的位置开始往后递增负数同样依次自增 13.枚举的应用应用枚举配合switch-caseenum day {mon1,tues,wen,thir,fri,sat,sun};int n;scanf(%d,n);switch(n){//case 1: //1是个冰冷的数字不够人性化case mon: //英语学得不错单词一看就会}七、头文件1.作用头文件用来包含其他头文件,函数的声明全局变量的声明结构体共用体枚举的定义内联函数等等2.自定义头文件2.1 和区别 --》通常用于自定义的头文件编译器默认会先从当前路径下寻找这个头文件如果找不到就去系统的环境变量系统默认的一系列路径这些路径就叫环境变量中查找头文件两个地方都找不到就报错(没有这个头文件) --》通常用于系统提供的头文件编译器默认去系统的环境变量中查找头文件环境变量系统指定的一个专门存放头文件的路径 --这个路径叫环境变量(ubuntu上头文件的环境变量是/usr/include)程序员可以使用-I(大写的i)自己指明头文件所在的位置 gcc *.c -o main -I/mnt/hgfs/share