UNIX系统 - 一些知识点

本文详细介绍了UNIX系统中的GCC编译过程,C文件扩展名的含义,预处理指令的使用,头文件的作用,环境变量的查看与配置,以及静态库和动态库的创建和应用。此外,还探讨了错误处理、环境表和C语言中的字符串处理技巧。
摘要由CSDN通过智能技术生成

一、GCC编译

gcc 编译器
gcc编译C程序时有4个步骤:
1 预处理,针对所有的指令(即以#开头),替换为纯C语法。(-E 生成.i文件)
2 编译(-S 生成.S文件)
3 汇编(高级语言转为汇编,汇编转为机器码)(-c 生成.o文件)
4 链接(.o文件链接)

通常境况下,把预处理、编译和汇编统称为编译(广义)
gcc -E 只做预处理,不做其他的。
gcc -E hallo.c -o hallo.i则生成.i文件
gcc -c 编译但不链接,生成.o文件
gcc -S 生成汇编文件,即.s文件
gcc -o 改变生成的文件的名字
gcc -Wall 显示更多的警告信息
gcc 编译加链接
gcc /-c/-o必须会。

二、C文件扩展后缀名

.a 静态对象库
.c 需要预处理的C语言源代码
.h C语言源代码头文件
.i 不需要预处理的C语言源代码
.o 目标文件
.s 汇编语言代码 .so 共享对象库
必须得有主函数才可以链接,但是可以用gcc -c编译

三、预处理指令

C程序中允许使用指令,指令就是以#开头的。指令在预处理阶段
转换为纯C语法。

指令分类:
1 #include (用于包含一个其他的文件,主要是头文件)
#include 后面支持两种格式:<>和"",区别是<>只查找系统的
文件路径,""会先查找当前目录,然后再查找系统路径。
2 #define 和 #undef定义/取消宏变量或宏函数
3 条件编译(即按条件选择编译的分支)
#if、#elif、#else、#endif
#ifdef、#ifndef
以上3条是最常用的指令

补充几个指令:
1 #error和#warning产生一个错误或警告
举例:(这里只是举个例子,一般没有人这样写)

#include <stdio.h>
#define VERSION 3
#if(VERSION < 3)
	#error "版本低"
#elif(VERSION > 3)
	#warning "版本高"
#endif

int main() {
   
	printf("hallo c\n");
	return 0;
}  

2 #pragma提供一些额外的功能
(1)#pragma GCC dependency 文件名

这个语句的含义是,让当前文件依赖于dependency后面的文件,
如果dependency后面的文件比当前文件新(修改的时间),就会产生警告。
(2) #pragma GCC poison 单词
定义某个单词为“毒药”,禁止使用,否则产生错误
注:在#pragma之前的代码可以使用,之后不能

(3)#pragma pack(int) - 这是比较实用的

对齐与补齐

 对齐 就是每个成员必须放在自己大小的整数倍位置(大于4字节的按4字节算)
 补齐 就是每个“结构”的大小应该是最大的成员的整数倍(大于4字节的按4字节算)
举例:
  struct s{
   
	char c1;
	int i;
	char c2;
  };/*则c1是第1个字节,i是第5到8个字节,c2是第9个字节,由于补齐原则,结
  *构体为12个字节*/
   struct s{
   
	char c1;
	short s;
	int i;
	char c2;
  };/*则c1是第1个字节,s是第3到第4个字节,i是第5到8个字节,c2是第9个字节,由于补齐原则,结
  *构体为12个字节*/
 struct s{
   
	char c1;
	short s;
	char c2;
  };/*则c1是第1个字节,s是第3到第4个字节,c2是第5个字节,由于补齐原则,结
  *构体为6个字节*/

对齐补齐浪费了空间,但是有寻址效率高的优点 有些时候,不需要对齐和补齐或者是改变对齐和补齐的单位 可以用pragma
pack()可以改变对齐和补齐的方式 比如:pack(1)按1字节对齐和补齐,其实就是不做对齐和补齐了。
pack(2)按2字节对齐和补齐。 举例:

#include <stdio.h>
#pragma pack(2)
int main() {
   
    struct s{
   
        char c1;
        int  i;
        char c2;
    };
	printf("size=%d\n",sizeof(struct s));
    return 0;
}
运行结果:size=8;

四、头文件

头文件(.h)中定义什么?
各种声明都应该定义在头文件中,是对外的清单。各种声明包括:变量声明
宏的声明、结构和联合、函数的声明。
各种声明具体的实现都定义在源文件(.c)中,是具体的代码。具体实现包括
变量的赋值、函数的代码。

头文件的基本格式:

  #ifndef XXXX_H_
  #define XXXX_H_
  //各种声明
  #endif

怎么用头文件写程序呢?
先写一个add.c文件
/这里add和add2这两个函数1不相互引用,所以不用写#include “add.h”/

int add(int a,int b){
   
	return a + b;
}

int add2(double a,double b){
   
	return a + b;
	
}

再写头文件add.h

#ifndef ADD_H_
#define ADD_H_
int add(int,int);
double add2(double,double);
#endif	

最后写由主函数的test.c文件

#include <stdio.h>
#include "add.h"

int main() {
   
	int r1 = add(2,3);
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值