在linux系统下进行C语言开发的学习
在linux系统下,C语言的编译是由gcc编译器(即释译工具)完成的
arm-linux-gcc 是arm的编译器即编译的是运行在arm开发板上的程序
arm-android-gcc 是android的编译器
参数:
-o 指定生成的目标
-E 预处理 即把所有的带#的编译指令替换为标准C (预处理指令不是标准C指令) gcc -o test.i -E test.c // -E 预处理 -o 目标文件
</pre> -S 编译成汇编 gcc -o test.s -S test.i <p></p><p> -c 编译机器码 (机器码:即机器语言) gcc -o test.o -c test.s</p><p> gcc -o test test.o //-o 目标为可执行程序, .o为依赖的机器码文件 </p><p> 三合一 直接生成.o</p><p> gcc -o test.o -c test.c </p><p> 四合一</p><p> gcc -o test test.c </p><p> 注意: 在将.o文件(机器码)编译成可执行程序的过程还包含一个链接的过程,在编写应用程序的情况下,把这一块封装了,在后面的博客中会进一步的详细的描述 。 </p><p></p><h3>多文件的编程与编译</h3><p> 多文件编程指的是: main(即入口函数)在一个.c 文件中,在这一个.c 中需要使用其它.c 中的函数或数据,那么其它.c文件需要提供.h文件作为接口。特别是在模块化开发时更应该使用多文件编程的方式开发。</p><p> 1).h 的写法</p><p> </p><pre name="code" class="cpp">#ifndef 宏名 //假设 该宏名没有定义,则编译下面代码
#define 宏名 //定义宏
扩展声明
#endif //结束编译条件
宏名的规范写法: 头文件的名称的大写 . 变成 _ 例如:头文件名称是:helle.h 则宏名可以使 HELLO_H
2)声明和扩展声明
int max(int x.int y); //函数的声明
int main(int argc,char **argv)
{
int a=12;
int b=23;
int c=max(a,b); //函数的调用
}
int max(int x,int y) //函数定义
{
return x>y?x:y;
}
3)静态声明以及扩展声明
static 修饰函数,代表这个函数只能在本文档中使用 (使用条件:不希望该函数被其它.c文件所调用,只是对外提供接口)
不用static 修饰的函数,代表全局函数,可以在任意文件中使用,但在编译时会找不到该函数,所以需要使用extern 作外部声明(在.h文件中)
例子;
//fun.h
#ifndef FUN_H
#define FUN_H
extern int max(int x,int y); //扩展声明
#endif
//fun.c
int max(int x,int y) //函数定义
{
return x>y?x:y;
}
//test.c
#include<stdio.h>
#include"fun.h" //引入头文件(编译时会进行替换-extern int max(int x,int y); )
int mian(itn argc,char **argv)
{
int a;
int b=23;
int c=max(a,b);
}
程序的调试
1、代码错误
(1)语法错误(哈哈 自己解决吧!!! 在这我也没办法一一指出,在后续的博客更新中,我会贴上我自己代码编写过程中遇到的语法错误)
(2)找不到.h文件
1)在.c文件中,#include“目录/头文件”
2)编译时用 -I 来指定头文件位置 gcc -o test test.c ./lib/fun.c -I ./lib
2.段错误
(1)参数需要的是内存地址,而给到的是其它类型 例 :scanf("%d %d",&a,b);
(2)定义了一个指针变量 ,而指针变量中没有赋地址值
int *p;
scanf("%d",p);
注意:通常定义一个指针变量后,一定使用malloc或new 分配内存进而初始化或者使用NULL进行初始化,在释放malloc或mew分配的内存后,一定使用NULL对该指针变赋值
3、编译或运行出错的调试方法
1)printf打印法
int main(int argc,char *argv[]){
printf("--------------- 1\n");
int a=12;
int b=0;
printf("--------------- 2 a=%d,b=%d\n",a,b);
int c=a/b;
printf("--------------- 3\n");
printf("---- %d\n",c);
printf("--------------- 4\n");
}
程序员常用方法 如果2打印,而3未打印,则代表2与3之间出现错误
2)调试工具法
编译时必须用 -g参数编译,然后用gdb调试,如下:
gcc -g -o test test.c fun.c
gdb ./test
当进入gdb后可使用如下指令
l [n][fun] 查看代码
例: l 查看所有代码
l 3 查看第三行周围的代码
l max 查看max函数
b [文件名:][n][fun] 设置断点
例: b 3 在第三行设置断点
b max 在函数max处设置断点
r 从前向后运行 遇到断点处停止
p 打印信号
n 单步执行 不会进入函数
u 单步执行 可跳出循环
s 单位步执行,可以进入函数内部
例:p a 打印变量a的值
p &a 打印a的地址
p a+2 打印变量a加2后的值
info break 查看断点信息
注意:我个人更加喜欢printf调试方法,不解释
ps:在嵌入式方面遇到的问题,希望大家能够与我一起进行讨论共同进步,个人邮箱:983177739@qq.com(只能留个QQ邮箱,虽然比较low,但不惧垃圾邮件,哈哈,因为垃圾邮件已经够多了)