笔者又来更新博客了,每次立下Flag说要一周一次更新博客,但总是拖,最后奈何4月份只更新了一次,说明四月份又浑浑噩噩度过了一个月,不过值得可喜的是笔者在4月份找了一份实习工作,在里面做嵌入式软件开发,目前负责QT的开发。
笔者目前的Linux环境是ubantu16.04,gnome桌面环境,使用Linux系统时间久了不免产生审美疲劳,所以笔者就换了个MacOS的主题环境,果然界面焕然一新,又可以开开心心的编程了。附上桌面环境图。
在Linux下各种文件的配置信息,难免会用到编辑器,而Vim就是一款强大的编辑器,当然C语言的编程也需要Vim编辑器输入,有很多人觉得VIm的操作繁琐,不容易记住很多指令,不过笔者觉得只要记住常用几个指令就足以应付这些了。
控制光标的移动、进行复制、粘贴、删除撤销等操作。通过 Ctrl+[ 可以返回到命令行模式。
光标的移动通过上下左右 键来进行移动,当然也可以通过k j h l 来移动,使用字母键进行字符移动时,可以在其前面加数字,表示在对应的放下上进行移动。
dd:表示删除一行,类似的ndd删除本行及下面的n行
yy:复制一行,nyy复制当前行和下面的n行
p:粘贴
u:撤销
只有在插入模式下,才可以进行文字的输入,按字母 i 可以进入插入模式,就能正常的进行操作了,就类似于word的操作一样了,然后上文也说过了,通过 Ctrl + [ 可以退出插入模式,进入命令行模式。
在退出插入模式后,按:可以进入底行模式,在底行模式下,可以进行文件的保存和退出。
:q :不保存直接退出vim编辑器。
:q! :不保存强制退出vim编辑器。
:wq :保存退出vim编辑器。
C语言的编程,必然需要编译链接成可执行文件。当然一般的C语言运行过程需要经过:预处理→编译→汇编→链接→可执行文件。在Linux环境下,可以使用gcc来编译链接生成可执行文件。
#include
int main()
{
int i,j;
for(i=0,j=5;i<j;i++)
printf("%d Hello World!",i);
return 0;
}
gcc test.c -o test.i -E
extern int pclose (FILE *__stream);
extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
#912 "/usr/include/stdio.h" 3 4
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
#942 "/usr/include/stdio.h" 3 4
#2 "test.c" 2
#2 "test.c"
int main()
{
int i,j;
for(i=0,j=5;i<j;i++)
printf("%d Hello World!",i);
return 0;
}
gcc test.i -o test.s -S
.LC0:
.string "%d Hello World!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0, -8(%rbp)
movl $5, -4(%rbp)
jmp .L2
gcc test.s -o test.o -c
gcc test.o -o test
./test
0 Hello World!1 Hello World!2 Hello World!3 Hello World!4 Hello World!
*****不过正常直接一步就可以生成可执行文件来运行。
gcc test.c -o test
./test
0 Hello World!1 Hello World!2 Hello World!3 Hello World!4 Hello World!
当然这只是单文件的C语言运行,如果涉及到多个文件的编译的时候,就需要注意到编译顺序了,被调用的文件需要先编译产生.o文件,然后再配合调用函数的.o文件一起生成可执行文件。接下来举个栗子。
主函数test.c文件,主要包含子文件:print.c、hello.c、和Add.c文件,都在主函数中调用。
#include
#include"print.h"
#include"hello.h"
#include"Add.h"
int main()
{
int a,b;
hello();
printf("请输入两个计算的数\n");
scanf("%d\n %d",&a,&b);
int c=Add(a,b);
print(c);
printf("\n结束!");
printf("终于学会make编译了!\n");
return 0;
}
hello.c和hello.h文件:也主要是打印,负责刚开始的内容输出。
#include"hello.h"
void hello()
{
printf("hello,world,今天开始学习make编译!\n");
}
//接下来是hello.h文件 ,只是负责对使用的函数进行声明。
#include
void hello();
print.c和printf.h文件:主要负责打印,当然直接就可以使用printf,我这里是为了说明生成可执行文件的编译顺序。
#include
#include"print.h"
void print(int c)
{
printf("c=%d ",c);
}
//接下来是print.h文件 ,只是负责对使用的函数进行声明。
#include"stdio.h"
void print(int c);
Add.c和Add.h文件:主要是对输入的两个数进行相加,返回输出结果,也是在主函数中调用。
#include
#include"Add.h"
int Add(int a,int b)
{
int c=a+b;
return c;
}
//接下来是Add.h文件 ,只是负责对使用的函数进行声明。
#include"stdio.h"
int Add(int a,int b);
由于在主函数中先调用的hello.c文件,所以你就先编译hello.c生成.o文件,当然你如果先编译Add.c或者print.c也是可以的,因为他们三个没有互相调用,当如果hello.c调用print.c中的函数,这个时候你就需要先编译print.c文件,然后才能编译hello.c文件。之后再将生成的目标文件链接相应的库生成可执行文件。接下来,就按照讲的顺序来编译运行链接运行一下程序。
gcc hello.c -o hello.o -c
gcc Add.c -o Add.o -c
gcc print.c -o print.o -c
gcc test.c -o test.o -c
gcc test.o print.o hello.o Add.o -o test
./test
hello,world,今天开始学习make编译!
请输入两个计算的数
12
34
c=46
结束!终于学会make编译了!
是不是有一点小开心,自己今天终于有收获了,进步就是这样一点点来的。
当然如果每次修改一下程序都要这样编译一下,是不是会觉得很浪费时间,当然这还是只有几个文件,如果出现上百个文件,岂不是时间都花在编译指令上了,调试起来太麻烦了,所以就出现了makefile文件,makefile文件中主要放的就是你程序的编译指令,通过make就可以直接执行makefile文件中的指令,就进行编译了,无需再慢慢每个文件进行编译了。接下来就看看makefile文件的编写规则。首先放一个我自己写的刚刚的那个工程的makefile文件。
test:test.o Add.o hello.o print.o
gcc -o test test.o Add.o hello.o print.o
test.o: test.c Add.h hello.h print.h
gcc -c test.c -o test.o
Add.o: Add.c Add.h
gcc -c Add.c -o Add.o
hello.o: hello.c hello.h
gcc -c hello.c -o hello.o
print.o: print.c print.h
gcc -c print.c -o print.o
clean:
rm *.o test
顶层需要写自己最后生成的目标文件,也就是可执行文件test,:感叹号后面的就是生成可执行文件需要用到的目标文件,下面就是生成可执行文件的指令,需要把所有的目标文件链接形成可执行文件。接下来就是目标文件的生成,需要用到-c这个指令,把每个.c文件都生成.o文件就可以了。最后一行的话,是清除生成的.o文件。接下来我们用makefile指令编译一下,make之后,就可以看到编译器有相应的输出,之后可以看到有可执行文件test了。
make
#编译器输出
gcc -c test.c -o test.o
gcc -c Add.c -o Add.o
gcc -c hello.c -o hello.o
gcc -c print.c -o print.o
gcc -o test test.o Add.o hello.o print.o
./test
hello,world,今天开始学习make编译!
请输入两个计算的数
12 34
c=46
结束!终于学会make编译了!
其中比较关键的两点需要注意的就是:
第一点是默认的makefile文件名有两种:makefile或者Makefile,这两种可以直接使用make指令,编译器是可以识别的,如果换成其他的文件,就需要用到-f指令了,例如
make
#编译器输出
make: *** 没有指明目标并且找不到 makefile。 停止。
make -f MakeFile
#编译器输出
make: 'test' is up to date.
第二点是makefile文件在书写编译指令的时候(第二行中gcc那一行),需要使用Tab键来空格,要不然会出现错误。