1.gcc 编程过程
gcc -o :output
gcc -o 输出文件名 输入文件名 -o后面不允许加入其他选项
运行输出文件 ./输出文件名
gcc -o 展开实际过程如下:
预处理
【gcc -E】 (替换过程,将include ,define 展开,替换)
编译
【gcc -S】 gcc -S a.c 将 .c 输出成 .s文件 生成汇编文件, mova ...
汇编
【gcc -c】gcc -c a.s 将.s文件生成.o 生成二进制文件
链接
【gcc -o】 gcc -o 输出文件名(可执行文件) 输入文件
即当直接输入 gcc -o 时,实际gcc先 -s 再 -c 最后 -o,也就是先编译后汇编最后链接 生成可执行文件,若想详细查看过程 可使用-v选项,会答应出来步骤
单步执行时,-E -S -c 都要加入-o 选项
预处理错误:
#include "name" //当前文件寻找
#include <name1> //系统文件中寻找
NOT FIND : 编译路径不对,解决方法: 【gcc -I】gcc -I 查找文件路径
连接错误:原材料不够 undefined xxx
1 .c中实现
2..h/.c 中声明,包含头文件路径
#define 宏 替换 ,不进行语法检查
#ifdef #else #endif
预定义宏
__FUNCTION__ : 函数名 //系统宏
__LINE__ : 行号
__FILE__:文件名
printf("the %s %s,%d\n",__FUNCTION,__FILE,__LINE__);
二 内存指针
内存编址:计算机的内存是一块用于存储数据的空间,由一系列连续的存储单元组成
变量的本质:定义一个变量的时候,实际上是向内存申请了一块空间来存放变量
大端: 将高位字节放在内存低地址
小端: 将低位字节放在内存低地址
指针:
int a=1;
int *p =&a;
为什么地址不能直接用变量来接收,却专门设置一个指针概念?
答:系统分不清你的变量是存放的指针还是一个地址,所以当你需要传递的参数的时候,系统无法判断出这个变量是传入的地址还是指针。
解引用:
p
中存储的是a
变量的内存地址,*p
就能通过地址去获取a
的值呢?
p
指针首先是一个变量,它本身也占据一块内存,这块内存里存放的就是 a
变量的首地址。
当解引用的时候,就会从这个首地址连续划出 4 个 byte,然后按照 int 类型的编码方式解释,这也是为什么指针前面要加入类型。
int p :变量p
int *p :指针
int p[3] : 存放整形的数组
int *p[3] :存放整型数据指针的数组
int (*p)[3]: 存放整形的数据的数组的指针
int **p :二级指针
int (*p)(void) :函数指针
int *p(void):函数指针
注意,指针本身占4 字节,
int *(p +1) : 在p所指向的地址上 加上sizeof(int)相当于数组 a【1】
*p ++ ,接应用后,给值加1
a. 指针与数组关系:
- int array[10]={0,1,2,3,4,5,6,7,8,9},value;
- value=array[0]; //也可写成:value=*array;
- value=array[3]; //也可写成:value=*(array+3);
- value=array[4]; //也可写成:value=*(array+4);
上例中,一般而言数组名array 代表数组本身,类型是int[10],但如果把array 看做指针的话,它指向数组的第0 个单元,类型是int* 所指向的类型是数组单元的类型即int。因此*array 等于0 就一点也不奇怪了。同理,array+3 是一个指向数组第3 个单元的指针,所以*(array+3)等于3。其它依此类推。
b . 指针与函数关系:
提前声明:
一个函数在编译之后,会占据一部分内存,而它的函数名,就是这段函数的首地址
可以把一个指针声明成为一个指向函数的指针。
int fun1(char *,int);
int (*pfun1)(char *,int);
pfun1=fun1;
int a=(*pfun1)("abcdefg",7); //通过函数指针调用函数。
可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为实参。
注意:&fun1 ==fun1 理解:
fun1 表示函数首地址,它的类型是 int 型
&fun1 一个指针指向整个函数的首地址,它的类型是int(*)()
c . 指针作为参数传递:传入的是地址,这样在某个模块内改变了指针所指向的地址中的值,外部变量也随之改变。
三. 位域
概念:有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可
struct {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
unsigned int d:1;
}x;
由于每个字段恰好为1位,所以只能为其赋值1或0(x.a=1;x.b=0)。变量x被储存在int大小的内存单元中,但是在本例中只使用了其中的4位。
struct pack {
unsigned a:2; // 取值范围为:0~3
unsigned b:4; // 取值范围为:0~15
unsigned c:6; // 取值范围为:0~63
};
注意:位域的存储同样遵循结构体内存对齐的规则