基础概念(8):汇总

1、cc是什么

总结卡片:
基础概念(8):汇总
“人和程序,有一个能跑就行”,意思是上班写代码,要么程序运行起来,要么人滚蛋。程序怎么才能运行起来呢?先要写出来,再编译成可执行的二进制,之后就可以跑起来了。这里重要的一环是这么编译程序,而cc就是做这个事情,cc就是编译器。
cc,我的电脑中它在这个位置下:
基础概念(8):汇总
cc是一个封装或替身,实现上它可以是clang-llvm,可以是gcc,可以是ghc,等等。
cc编译器有不同的实现,我电脑中它是clang-llvm:
基础概念(8):汇总
换个说法,cc是一个转换器,把人看的程序转换成硬件执行的指令。

2、怎么用cc来编译

总结卡片:
基础概念(8):汇总
cc的使用可以很简单,指定要转换的程序文件就可以了,比如:cc hello.c。
按cc的规则(我这里是clang-llvm),程序文件以.c或.cpp为后缀。
cc有很多功能,以参数来指定功能,参数可以用命令 cc -help 来查看。
cc hello.c,转换出来的就是当前设备可以执行的二进制,统一叫:a.out,执行它:./a.out
可执行文件怎么命名都可以,不影响执行,也可cc时指定二进制文件的名字:
cc hello.c -o hello
换个说法,cc是转换器,填入程序文件,就会有转换的东西出来。

3、怎么写一个c程序

总结卡片:
基础概念(8):汇总
遵循c语言的规则,即可写出c程序。规则下有两个重要概念:函数与变量。
就好像游戏中的打仗,要考虑怎么打,谁来打。
“怎么打”就是流程,把流程封装起来就是函数,流程也叫算法。
“谁来打”就是变量,变量组合出,或抽象为数据结构。
一个c程序,包括算法与数据结构,也就是函数与变量。
一个简单c程序,可以只有main函数,main函数是c规则中不能缺少的函数,也是“自动”执行到的函数(且不能自行调用)。在main函数中写你的流程就可以了,需要什么变量就定义出来。
helloworld程序:

#include <stdio.h>
int main() {
	printf("hello world\n");
	return 0;
}

程序文件有了,再用cc把它转换成可执行文件,可查看执行效果。

4、怎么写一个排序算法

总结卡片:
基础概念(8):汇总
怎么写一个排序算法?
程序初衷是解决问题,重点关注流程的设计,怎么去解决问题,而不是关注代码本身。
排序就是从低到高地排队。
事物都能用数值来表达,数值排序很常见。
排序算法很多,这里介绍一个“进化论”算法:
随机拿到两个数字,一左一右,如果左边大于右边,就把两者交换(即总是让左边的小),否则不操作。
把这个操作循环执行上万次,即不断进化,最终可实现升序排序。
设计好流程后,就可以用c来写了:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
	int arr[] = {890,19,10,12,4,20,6,11,3,100,23,44,12,130,3000,34};
	int count = sizeof arr / sizeof *arr;
	for (int i=0; i<count; i++) {
		printf("%d,",arr[i]);
	}
	printf("\n");
	unsigned int times=0;
	srand(time(0));
	while (times < 1000) {
		int i = rand()%count;
		int j = rand()%count;
		if (i < j && arr[i] > arr[j]) {
			int tmp = arr[i];
			arr[i]=arr[j];
			arr[j]=tmp;
		}
		times++;
	}
	printf("\n");
	for(int i=0; i<count; i++) {
		printf("%d,", arr[i]);
	}
	printf("\n");

	return 0;
}

cc它,再执行:
基础概念(8):汇总

5、怎么声明变量

总结卡片:
基础概念(8):汇总
c有一个规则:所有东西都要先声明再能使用。函数是这样,变量也是这样,先声明再使用。
c是强类型语言,声明时一定要把类型给指明。
所以变量声明离不开类型。
变量常见的基本数据类型:
char --字符型,一个字节
short --短整型,二个字节
int --整型,一般4个字节
long --长整型,一般8个字节
float --单精度浮点型,一般4个字节
double --双精度浮点型,一般8个字节
这些数据类型到底占几个字节跟当前运行二进制程序的设备有关,因为类型的实现是由当前设备提供的(比如设备提供的二进制文件libc实现了这些类型,而c程序依赖于这个文件)。可以用c的操作符sizeof,来查看当前设备实现数据类型时到底用了几个字节:

#include <stdio.h>
int main() {
	printf("char\t%lu\n", sizeof(char));
	printf("short\t%lu\n",sizeof(short));
	printf("int\t%lu\n",sizeof(int));
	printf("long\t%lu\n",sizeof(long));
	printf("float\t%lu\n",sizeof(float));
	printf("double\t%lu\n",sizeof(double));
	return 0;
}

我电脑上运行结果:
基础概念(8):汇总
怎么声明变量?类型名+变量名,比如:
int age;
float weight;
char code = 'c';
double temper = 36.6;

6、怎么释放人力

总结卡片:
基础概念(8):汇总
越来越多人为的事情都交给程序跟机器来完成了,以前的计算,现在的洗碗扫地,再到情感交流,程序改变着世界,也在释放人力。
你也可以写程序,让它帮你做事。程序可以做很多事情,特别是重复类的事情。
重复的事情交给程序来做,让它循环地做。
c里面经常使用的循环语句是while跟for。
比如,计算1+2+3+...+100,叫设备“粗暴”运算,你都不用动脑子:

#include <stdio.h>
int main() {
	int sum=0;
	for(int i=1;i<=100;i++) sum+=i;
	printf("sum=%d\n", sum);
}

比如,检查集合里面有多少个数字33,你不用担心看错看漏:

#include <stdio.h>
int main() {
	int arr[] = {1, 22, 33, 22, 22, 3, 33, 904, 33, 93, 22, 33};
	int cnt = sizeof arr / sizeof *arr;
	int i=0, num=0, target=33;
	while (i<cnt) {
		if (arr[i] == target) num++;
		i++;
	}
	printf("%d has %d\n", target, num);
}

当然while与for不只释放人力,它还可以做很多事情,大到支撑起一个系统,小到循环任务的设计--比如以下这个程序循环地生成随机数值,直到命中目标值:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
	int target = 3;
	printf("target=%d\n", target);
	srand(time(0));
	int limit = 10;
	int now = rand() % limit;
	while (now != target) {
		printf("now=%d\n", now);
		now = rand() % limit;
	}
	printf("now is target\n");
	return 0;
}

cc后执行,一个结果:
基础概念(8):汇总

7、函数间怎么传递数据

总结卡片:
基础概念(8):汇总
c的函数间通过数值来传递,不管是基本类型的变量值,还是数组的地址、指针的值,传递的都只是一个数值,这个数值拷贝到被调用函数的临时变量中。
被调用函数的临时变量得到这个值后,想怎么修改都行,但都不会影响到调用函数里面的值。

#include <stdio.h>
int power(int a, int b) {
	int r;
	for(r=1;b>0;b--) r=r*a;
	return r;
}
int main() {
	int a=2,b=10;
	printf("power(2,10)==%d\n", power(a,b));
	return 0;
}

比如上面代码,power函数中修改了变量b,并不会影响到main函数中的变量b。
c函数没有“引用”的概念,如果想修改调用函数里面的数据,可以用数组或指针等做到,比如用数组:

#include <stdio.h>
#define MAX_LEN 1024
int line(char c[], int len) {
	int rlen=0;
	char ch;
	while(rlen<len-1 && (ch=getchar()) != '\n') {
		c[rlen++] = ch;
	}
	c[rlen] = '\0';
	return rlen;
}
int main() {
	char c[MAX_LEN];
	int len = line(c,MAX_LEN);
	printf("len==%d\n",len);
	printf("%s\n", c);
	return 0;
}

main调用line时,把字符数组c传递过去,实际是把数组的地址传递过去,line函数拿到数组c,就能修改到main函数中的数组的内容,因为line跟main的数组地址,指向同一个内存块。

上一篇:2_策略模式


下一篇:webrtc中Transport-CC带宽计算流程