1、cc是什么
总结卡片:
“人和程序,有一个能跑就行”,意思是上班写代码,要么程序运行起来,要么人滚蛋。程序怎么才能运行起来呢?先要写出来,再编译成可执行的二进制,之后就可以跑起来了。这里重要的一环是这么编译程序,而cc就是做这个事情,cc就是编译器。
cc,我的电脑中它在这个位置下:
cc是一个封装或替身,实现上它可以是clang-llvm,可以是gcc,可以是ghc,等等。
cc编译器有不同的实现,我电脑中它是clang-llvm:
换个说法,cc是一个转换器,把人看的程序转换成硬件执行的指令。
2、怎么用cc来编译
总结卡片:
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程序
总结卡片:
遵循c语言的规则,即可写出c程序。规则下有两个重要概念:函数与变量。
就好像游戏中的打仗,要考虑怎么打,谁来打。
“怎么打”就是流程,把流程封装起来就是函数,流程也叫算法。
“谁来打”就是变量,变量组合出,或抽象为数据结构。
一个c程序,包括算法与数据结构,也就是函数与变量。
一个简单c程序,可以只有main函数,main函数是c规则中不能缺少的函数,也是“自动”执行到的函数(且不能自行调用)。在main函数中写你的流程就可以了,需要什么变量就定义出来。
helloworld程序:
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
程序文件有了,再用cc把它转换成可执行文件,可查看执行效果。
4、怎么写一个排序算法
总结卡片:
怎么写一个排序算法?
程序初衷是解决问题,重点关注流程的设计,怎么去解决问题,而不是关注代码本身。
排序就是从低到高地排队。
事物都能用数值来表达,数值排序很常见。
排序算法很多,这里介绍一个“进化论”算法:
随机拿到两个数字,一左一右,如果左边大于右边,就把两者交换(即总是让左边的小),否则不操作。
把这个操作循环执行上万次,即不断进化,最终可实现升序排序。
设计好流程后,就可以用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它,再执行:
5、怎么声明变量
总结卡片:
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;
}
我电脑上运行结果:
怎么声明变量?类型名+变量名,比如:
int age;
float weight;
char code = 'c';
double temper = 36.6;
6、怎么释放人力
总结卡片:
越来越多人为的事情都交给程序跟机器来完成了,以前的计算,现在的洗碗扫地,再到情感交流,程序改变着世界,也在释放人力。
你也可以写程序,让它帮你做事。程序可以做很多事情,特别是重复类的事情。
重复的事情交给程序来做,让它循环地做。
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后执行,一个结果:
7、函数间怎么传递数据
总结卡片:
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的数组地址,指向同一个内存块。