gcc默认形成的可执行程序是动态链接的
gcc -static形成的可执行程序是静态链接的
告诉可执行程序,动态库(共享库)的地址在哪
优点:形成可执行程序的体积小
缺点:一旦缺失,所有依赖动态库的程序都会报错
将库实现,在链接阶段拷贝到我们的可执行程序中
优点:一旦编译好,不依赖任何库
缺点:浪费空间(磁盘、内存空间和网络等)
make是一个命令
Makefile是一个文件
Makefile是一个自动化构建的工具
例子:
创建一个.c文件,在里面写入代码
在创建一个Makefile文件,里面写入如下代码。表示mycode文件依赖于code.c,下面就是正常的gcc编译
最后输入make指令运行mycode,就会生成一个叫mycode的可执行文件
然后运行就行
依赖关系和依赖方法,形成目标文件
第一行表示:依赖关系,mycode的形成依赖于code.c
第二行表示:依赖方法,mycode的形成依赖于code.c,以gcc code.c -o mycode的方法形成
mycode:目标文件
code.c:依赖文件。若依赖文件有多个,则叫依赖文件列表
gcc code.c -o mycode
clean也是一个目标文件,不过它的依赖文件是空的,下面则是它的依赖方法
为什么但输入一个make只形成一个目标文件?(如果把“clean:”放到第一个,单输入一个make就是形成"clean"目标文件)
makefile文件中,保存了编译器和链接器的参数选项,并且描述了所有源文件之间的关系。make程序会读取makefile文件中的数据,然后根据规则调用编译器,汇编器,链接器产生最后的输出
默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件, 找到了解释这个文件
当make执行一次生成mycode目标文件后,为什么不能再执行?又是怎么做到的?
要更新一个以存在的文件的ACM时间
touch+文件名
mycode文件依赖的其实是code.o文件。
在执行依赖方法时,生成的文件可以通过clean删除
BIN赋值为mytest(目标文件)
SRC动态的获取所有源文件
OBJ赋值为依赖文件
CC赋值为gcc
RM赋值为rm -f
@echo:不让echo回显
BIN赋值为mytest(目标文件)
SRC=动态的获取所有源文件(wildcard是Makefile自身语法包含的函数)
OBJ=(SRC:.c=.o表示将所有的.c换成.o形成可执行程序。这是Makefile自己的语法)
CC赋值为gcc
RM赋值为rm -f
^:表示将所有的OBJ文件放到(CC)后,也可以理解为:^就是OBJ
$@:表示我们要形成的目标文件
%.o:%叫通配符,也是makefile的语法,表示匹配任意内容。允许你匹配一组文件名,而不需要显式地列出每一个文件名
%.c:表示匹配所有的.c文件
$<:表示将所有的.c文件一个一个的交给对应的命令,一个一个的形成.o
@:不让echo回显
BIN=mytest
2 #SRC=$(shell ls *.c)
3 SRC=$(wildcard ls *.c)#动态的获取所有源文件(wildcard是Makefile自身语法包含的函数)
4 OBJ=$(SRC:.c=.o)
5 CC=gcc
6 RM=rm -f
7
8 $(BIN):$(OBJ)
9 $(CC) $^ -o $@
10 @echo "链接 $^ 成 $@"
11 %.o:%.c
12 $(CC) -c $<
13 @echo "编译 $< 成 $@"
14
15 .PHONY:clean
16 clean:
17 $(RM) $(OBJ) $(BIN)
18
19 .PHONY:test
20 test:
21 @echo $(BIN)
22 @echo $(SRC)
23 @echo $(OBJ)
回车(Carriage Return,简称CR)起源于早期的打字机时代。在打字机上,有一个按键被称为回车键,按下这个按键会使打字机的滑块(或称为打印头)回到左侧边缘,同时纸张也会向上移动一行,以便继续输入文字。因此,这个按键被命名为“回车键”,因为它实现了“回车”到下一行的功能
换行的概念:光标换一行,同一列不同行
#include<stdio.h>
#include<unistd.h>
int main()
{
//linux下一切皆文件,往显示器中打印就是往显示器中写入,加\n表示立即写入
printf("hello world\n"); //没有\n,在linux下会先停两秒在输出
sleep(2);
return 0;
}
休眠两秒再出来是因为程序先执行的“sleep”吗?
c语言执行代码是自上向下执行的,不可能先执行sleep。当程序执行sleep休眠时,printf肯定已经执行完了
既然printf已经执行完了,为什么在sleep期间没有看到字符串打印?
此时字符串在一个叫做“缓冲区”的地方。这个缓冲区是为显示器提供的,既然有缓冲区,那必然就会有刷新策略,而显示器的刷新策略就是:行刷新。如果我碰到的打印的字符串包含“\n”,该消息就会立即显示到显示器上
如果不想换行,就让字符串立即打印到显示器上,怎么做?
用fflush()进行强制刷新。c语言在输入输出时,默认打开了三个文件的输入输出流:stdin(键盘)、stdout、stderr(这两个都是显示器)。printf进行打印时,实际上是把消息写到了stdout里面。如果消息没刷新出来,只要用fflush()刷新一下stdout就行
#include<stdio.h>
#include<unistd.h>
int main()
{
int cnt=10;
while(cnt>=0)
{
//如果不加"2",从10-0输出则会呈现:10、90、80、...
//因为%d的意思是将输出的内容进行格式化,就是将一个整数格式化为一个字符
//10格式化后为两个字符,|1|0|。除去10之外的都是一个字符,只占一位,所有会出现10、90、80...的情况
printf("%-2d\r",cnt); //左对齐
fflush(stdout);
cnt--;
sleep(1);
}
// printf("hello world");
// fflush(stdout);
//sleep(2);
return 0;
}
1秒=1000毫秒=1000微妙*1000
#include "process.h"
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
//函数指针类型
typedef void (*call_t)(const char*,double,double);
double total = 1024.0;
//double speed = 1.0;
double speed[] = {1.0, 0.5, 0.3, 0.02, 0.1, 0.01};
//回调函数
void download(int total, call_t cb)
{
srand(time(NULL));
double current = 0.0;
while(current <= total)
{
cb("下载中", total, current); // 进行回调
if(current>=total) break;
// 下载代码
int random = rand()%6;
usleep(5000);
current += speed[random];
if(current>=total) current = total;
}
}
void uploadload(int total, call_t cb)
{
srand(time(NULL));
double current = 0.0;
while(current <= total)
{
cb("上传中", total, current); // 进行回调
if(current>=total) break;
// 下载代码
int random = rand()%6;
usleep(5000);
current += speed[random];
if(current>=total) current = total;
}
}
int main()
{
download(1024.0, FlushProcess);
printf("download 1024.0MB done\n");
download(512.0, FlushProcess);
printf("download 512.0MB done\n");
download(256.0,FlushProcess);
printf("download 256.0MB done\n");
download(128.0,FlushProcess);
printf("download 128.0MB done\n");
download(64.0,FlushProcess);
printf("download 64.0MB done\n");
uploadload(500.0, FlushProcess);
return 0;
#include "process.h"
#include <string.h>
#include <unistd.h>
#define SIZE 101
#define STYLE '='
//v2: 根据进度,动态刷新一次进度条
void FlushProcess(const char *tips, double total, double current)
{
const char *lable = "|/-\\";
int len = strlen(lable);
static int index = 0;
char buffer[SIZE];
memset(buffer, 0, sizeof(buffer));
double rate = current*100.0/total;
int num = (int)rate;
int i = 0;
for(; i < num; i++)
buffer[i] = STYLE;
printf("%s...[%-100s][%.1lf%%][%c]\r", tips, buffer, rate, lable[index++]);
fflush(stdout);
index %= len;
if(num >= 100)printf("\n");
}
// v1: 展示进度条基本功能
void process()
{
int rate = 0;
char buffer[SIZE];
memset(buffer, 0, sizeof(buffer));
const char *lable = "|/-\\";
int len = strlen(lable);
while(rate <= 100)
{
printf("[%-100s][%d%%][%c]\r", buffer, rate, lable[rate%len]);
fflush(stdout);
buffer[rate] = STYLE;
rate++;
usleep(10000);
}
printf("\n");
}