2019独角兽企业重金招聘Python工程师标准>>>
Head first C
cppcourse c part
K&R C Bible
##Head first C
P6:如果想检查program的exit status, windows使用echo %ErrorLevel%, Linux使用echo $? (钱的问题)
P9:顺序执行两条命令
gcc zork.c -o zork && ./zork --Linux
gcc zork.c -o zork && zork --Windows
P32: 给gcc加上-std=99以支持C99标准.
续1:
P56: sizeof是一个操作符而不是函数,sizeof在编译时就已经完成计算
P59: char s[] = "How big is it?"
对s取地址就是s自身 --> &s == s
sizeof(s) is 15
什么是Pointer decay
当你把array赋值给pointer的时候,pointer仅包含了array的地址信息! pointer并不知道array的大小,
信息在传递/赋值过程中丢失了,这种现象叫做pointer decay,
当你把array传递给function的时候,array自动转成pointer(也就是function中的形参array实质上变成了pointer),产生了一次pointer decay.
sizeof(array)是数组实际占用空间的大小, sizeof(pointer)总是4或8
续2:
P61: An array variable can be used as a pointer to the first element in an array.
array变更名可以看作是指向数组中第一个元素的指针, 因此s[0]和*s是等价的
P65:
scanf
char name[40];
int age;
scanf("%39s %i",name, &age)如果不加39,则可能导致buffer overflow,同时可输入两个变量的值,以space分隔.
fgets -> 更安全的scanf
char food[5];
fgets(food,sizeof(food),stdin):
参数1:指向buffer的pointer, 参数2:buffer的大小(和scanf不一样,它是算上\0的总大小,无需减1), 参数3:数据从哪儿来
区别:
scanf可以一次输入多组数据,fgets不行,scanf胜出
scanf %s不接受空格所以不能一下输入多个单词,fgets胜出
fgets强制你必须指定大小,scanf大小是可选的, fgets胜出
P72,73. char[] cards= "JQK" 与char* cards= "JQK"的区别
1)做为形参,它们没区别
2)如果是在函数内部
char* cards在栈区保存了常量区"JQK"的地址, char[]在栈区新拷贝了一份常量区"JQK"的内容
Geek怎么做?
不要让char*指向字符串常量或者总是加上const关键字const char *s = "some string",这样编译时就可以发现错误.
P111重定向input
./geo2json < gpsdata.csv
重定向input & output
./geo2json < gpsdata.csv > output.json
P122
fscanf(stdin, "%s", s) == scanf("%s",s)
fprintf(stdout, s) == printf(s)
重定向input & stdout & stderr
./geo2json < gpsdata.csv > output.json 2> errors.txt
P135
可以把使用|(管道)连接的两个程序看成一个整体,和先前一样使用输入和输出重定向
(./bermuda | ./geo2json) < spooky.csv > output.json
使用|连接的程序是同时执行的,第2个进程并不一定要等到第1个执行完再开始, 一连串用pipe连接的进程叫pipeline
<仅作为第1个进程的标准输入, >仅作为最后一个进程的标准输出,()是必须的.
P138文件流
每个data stream用指向文件的指针表示: r,w,a分别表示read,write, append
FILE *in_file = fopen("input.txt","r");
FILE *out_file = fopen("input.txt","w");
FILE *out_file = fopen("input.txt","a");
P149 getopt用法,见我的另一篇博客
P191
gcc -c *.c //create object code for every file
gcc *.o -o launch //link everything together
生成 .o文件以节省下次的编译时间
每种rule包含一行dependencies(冒号前的部分叫做target) 和 一行以tab开头的recipe,
(to be continued)
##cppcourse c part
Episode 24:
以下演示了指针只不过是地址(将结构体拷贝到字符数组中,然后将数组名强制转换成结构体指针)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char sno[5];
char sname[32];
int sage;
} student_t;
int main(void){
student_t stu;
strcpy(stu.sno, "1001");
strcpy(stu.sname,"cyper");
stu.sage = 20;
char str[sizeof(stu)];
memcpy(str,&stu,sizeof(stu));
student_t* p = (student_t*)str;
printf("%s %s %d\n",p->sno,p->sname,p->sage);
return 0;
}
不能像这样给sno赋值,
stu.sno="1001"
报错:
24_1.c:13:13: error: incompatible types when assigning to type ‘char[5]’ from type ‘char *’
原因:在定义申明完数组后数组名具有常量特性,表示数组存储空间的开始地址,而C语言中不能对常量赋值。
结构体定义时不能定义自身结构体变量,但可以定义自身的指针.
Episode25:
void (*f)(int) 函数指针, void* f(int)函数f返回值为指针
等价关系 -> &f == f,类似于数组首地址, 调用时(*f)(100) == f(100)