还是C语言

还是C语言
首先说c语言的编译环境包括,翻译环境和执行环境,所谓的编译环境是,将程序翻译成
指令格式,所谓的执行环境这就是标准说明在一台机器上运行,这就牵扯到所谓的操作系统
交叉编译器。
关于程序编译,编译出来的.i文件就是编译器翻译展开的文件
1.条件编译
#include<stdio.h>
#define C 1
int main()
{
#if(1==C)
printf("printf 1 print ");
#else
printf("printf 2 print ");
#endif
return 0;
}

#include<stdio.h>
#define C 1
int main()
{
if(1==C)
printf("printf 1 print ");
else
printf("printf 2 print ");


return 0;
}
二者的结果相同,但是而这个程序可以通过gcc
生成.i文件可以发现前者就是简单的替换,


后者则是需要判断之后再执行
二者预编译结果显示,这下面值显示main函数部分,对于都文件不显示
对于程序1是:
main()
{
printf("printf 1 print ");
return 0;
}


程序2:


main()
{
if(1==1)
printf("printf 1 print ");
else
printf("printf 2 print ");
return 0;
}
感想:在这个程序的编译过程中我们可以发现一个问题就是宏定义,我们不需要修改代码页
可以在命令中实现,
@root  gcc -E -DC==1/*宏定义*/ -o 生成文件名.i 即可编译完成;
2.关于头文件。
在头文件中出现几次调用的情况。
比如:在同一个文件之中包含以下几个文件
test.c
#include <stdio.h>
#include "test.h"
#include "test.h"
#include "head.h"
#include "head.h"
int main()
{
f();
printf("%s\n",name);
return 0;
}


test.h
#ifndef  TEST_H
#define TEST_H
#include <stdio.h>
#include  "head.h"
const char name="hello word";
void f()
{
printf("%s",name);
}
head.h


#ifndef HEAD_H
#define HEAD_H
int head =1;
#endif


假如不适用条件编译在调用test.c时会报错,有重定义发生,但是只要
我们使用条件编译,头文件可以无限包含
这就是在linux内核中为什么可以头文件可以包含多个原因
3.关于error和warning的使用
介绍一般#error message是给程序员特意的编译错误消息,
类似的 #warning 一般都会回产生错误但是不会提示警告:
#include<stdio.h>
#define CON_1 "CON_1"
#define CON_2 "CON_2"
int main()
{


#ifndef COMM
#warning Compling will be stoped
#error No define Constant symbol
#endif
printf("%s\n",COMM);
printf("%s",CON_1);
printf("%s",CON_2);
return 0;
}
此处定义的宏是COMM程序在执行过程之中
会检测假如程序未定义COMM的话会程序会产生警告和错误并且终止。
条件测试的出现未产品的测试和发布都提供了很好地技术支持;
4.#line 用于强制指定新的行号和编译文件名
并对源文件的代码重新编号。
#line number filename (filename可以省略)
#include <stdio.h>
#line 14 "sxp.c"
#define CON_1 "CON_1"
#define CON_2 "CON_2"
void f()
{
return 0;
}
int main()
{


printf("%s\n",CON_1);
printf("%s\n".CON_2);
printf("%d",_LINE_);//编译器自带的宏定义
printf("%s\n",_FILE_);//同上
f();
return 0;
}


例子中的#LINE的宏定义表示在这个宏定义的下一行是14行。。
c库中引入的line的意义就是程序的无关性,一般就是指定
自己的代码段用于调试使用


5.#pragma是编译器指示字,用于编译器完成特定的动作
编译器和操作系统特有,不可在不同编译器之间移植


#pragma parameter 
#pragma message 输出编译的消息
例子:
注:vc中有message,在linux 中的gcc将其忽略


#include <stdio.h>
#if defined (ANDROID20)
#pragma message (" complie android ...");
#define VERSION "Android 2.0"
#elseif defined(ANDROID23)
#pragma message (" complie android 23...");
#define VERSION "Android 2.3"
#else
#error compline versin is not proved!
int main()
{
printf("$s",VERSION);
return 0;
}
#pragma pack
内存对齐,不同的数据在内存中按照一定的顺序排放,不是顺寻的
一个挨着一个排放。
pragma pack这个关键字可以指定cpu的内存编译器对齐的方式
例子:
#pragma pack(2)
{
char c;
short s;
}
以2个字节读写,
这个struct的大小是:
#pragma pack(4)
{
char c;
short s;
}
以4个字节读写,
这个关键字可以排除编译器的硬件异常情况发生


6.关于cpu读写字节,一般是按照2^n读写的。
列子:struct T
{
char c;
short s;
}


这个例子中char占用一个字节,short占有2字节,所以一共是三个字节
但是cpu会把其当作4个字节读取,写入;
7.关于#与##运算符运算符
#include<stdio.h>
#define NAME(n) name##n
int main()
{
int NAME(1);
int NAME(2);
NAME(1)=1;
NAME(2)=2;
printf("%d\n%d\n",NAME(1),NAME(2));
return 0;
}
巧妙运用:
#include<stdio.h>
#define STRUCT(type) typedef struct _tag_##type type;\
struct _tag_##type


STRUCT(Stucdent)
{
char *name;
int id;
}
int main()
{
Stucdent s1;
Stucdent s2;
s1.name="s1";
s1.id=0;


s2.name="s2";
s2.id=1;
printf("%s\n",s1.name);
printf("%d\n",s1.id);


printf("%s\n",s2.name);
printf("%d\n",s2.id);
return 0;
}


翻译之后的是
typedef struct _tag_Student Student;struct _tag_Student{
char *name;
int id;
};
............
注:利用gcc 命令生成.i文件。查看最后源代码





















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值