c语法深入学习

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. 指针与数组关系:

  1. int array[10]={0,1,2,3,4,5,6,7,8,9},value; 
  2. value=array[0]; //也可写成:value=*array; 
  3. value=array[3]; //也可写成:value=*(array+3); 
  4. 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

};

注意:位域的存储同样遵循结构体内存对齐的规则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值