《C程序设计语言》

最近,一边在改paper,一边快速的翻看了一下《C程序设计语言》,记录了一下读书的笔记,文末附有其他人的读书笔记,对比起来,相差甚远,惭愧!

第一章

字符输入/输出

getchar();//通常通过键盘输入
putchar();

'c'和"c"不同,后者多个'\0'

在复制文件内容时,可以使用getchar();

#include 
/* 将输入复制到数出 */
main()
{
    int c;
    while ((c = getchar()) != EOF) //学这种写法,在Linux那本书很多这种写法
        putchar(c);
}

书里面有一句:在C语言,所有函数参数都是“通过值”传递的。

第二章

extern声明:单独放在一个头文件声明。

分清楚"定义"和"声明"

枚举常量

enum boolean {NO, YES};

任何变量的声明都可以使用const限定符限定,该指定的变量的值不能修改。

.c文件 -- 编译 --> .o文件 -- 加载(链接)--> a.out

cc main.c getline.c strindex.c
//编译这3个文件,并把生成的目标代码分别存放在文件main.o getline.o strindex.o中,然后再把这3个文件一起加载到可执行文件a.out
cc main.c getline.o strindex.o
//对main.c进行修改后,可对main.c重新编译,和之前两个.o文件一起加载到可执行文件

逆波兰表示法:用栈来实现

第四章

外部变量

构成C语言程序的函数与外部变量可以分开进行编译。一个程序可以存放在几个文件中,原先已编译的函数可以从库中进行加载。注意几个问题:

  • 如何进行声明才能确保变量在编译时被正确声明?
  • 如何安排声明的位置才能确保程序在加载时各部分能正确连接?
  • 如何组织程序中的声明才能确保只有一份副本?
  • 如何初始化外部变量?

如果要在外部变量定义之前使用该变量,或者外部变量的定义与变量的使用不在同一个源文件中,则必须在相应的变量声明中强制性地使用关键字extern

在一个源程序的所有源文件中,一个外部变量只能在某个文件中定义一次,而其他文件可以通过extern声明来访问它(定义外部变量的源文件中也可以包含对给外部变量的extern声明)

Ex1:

//file1
extern int sp;
extern double val[];
...
//file2
int sp = 0;
double val[MAXVAL];

Ex2:

//file1
extern int sp;
extern double val[];
...
int sp = 0;
double val[MAXVAL];

静态变量

用static声明限定外部变量与函数,可以将其后声明的对象的作用域限定为被编译源文件的剩余部分。

static的作用??

寄存器变量

register声明告诉编译器,它所声明的变量在程序中使用频率较高。其思想是,将register变量放在机器的寄存器中,这样可以使程序更小,执行速度更快。

递归

递归实现快速排序

C预处理器

  • 文件包含
#include "文件名"
#include <文件名>
  • 宏定义 (注意宏定义的使用,例如要记得加括号)
#define 名字 替换文本
//替换文本是任意的,如下:
#define MAXVAL 100
#define forever for(;;)  /*无限循环*/
#define MAX(A,B) ((A) > (B) ? (A) : (B))  /*看着像函数,实际只是起文本替换作用*/
  • 注意
#undef getchar   //取消getchar宏定义

//为了保证hdr.h文件的内容只被包含一次
#if !define(HDR)  or  #ifndef HDR
#define HDR
/* hdr.h文件的内容放在这里 */
#endif

//先测试系统是哪个版本的,引入对应的头文件
#if SYSTEM == SYSV
    #define HDR "sysv.h"
#elif SYSTEM == BSD
    #define HDR "bsd.h"
#elif SYSTEM == MSDOS
    #define HDR "msdos.h"
#else
    #define HDR "default.h"
#endif
#include HDR
第五章
  • 指针与函数参数

由于C语言是以传值的方式将参数值传递给被调用函数,因此,被调用函数不能直接修改主调函数中变量的值。

void swap(int x, int y){
    int temp;
    temp = x;
    x = y;
    y = temp;
}
int mian(){
    int a = 10, b = 20;
    swap(a, b);//无法实现交换,该函数仅仅交换了a和b的副本的值
}

那应该怎么办呢?传值变成传指针!!!

void swap(int *x, int *y){ /* 交换*x和*y */
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}
int mian(){
    int a = 10, b = 20;
    swap(&a, &b);//传指针,指针参数使得被调用函数swap能够访问和修改主调函数main中对象的值
}
  • 指针与数组
//在函数定义中,形式参数
char s[];和char *s;是等价的  //char *s; 是字符指针
  • 指针数组以及指向指针的指针
void qsort(char *v[], int left, int right){
    int i, last;
    void swap(char *v[], int i, int j);
    if (left >= right)
        return;
    swap(v, left, (left + right)/2);
    last = left;
    for (i = left+1; i <= right; i++)
        if (strcmp(v[i], v[left]) < 0)
            swap(v, ++last, i);
    swap(v, left, last);
    qsort(v, left, last-1);
    qsort(v, last+1, right);
}
void swap(char *v[], int i, int j){
    char *temp;
    temp = v[i];
    v[i] = v[j];
    v[j] = temp;
}
  • 命令行参数
int main(int argc, char *argv[]) {} //字符指针数组,数组元素是字符指针
  • 指向函数的指针
void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
int (*comp)(void *, void *) //表明comp是一个指向函数的指针,该函数具有两个void*类型的参数,其返回值类型为int。

C++的qsort:qsort函数定义在头文件

void qsort (void* base, size_t num, size_t size,
            int (*compar)(const void*,const void*));
int compar (const void* p1, const void* p2);
//example
/* qsort example */
#include       /* printf */
#include      /* qsort */

int values[] = { 40, 10, 100, 90, 20, 25 };

int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}

int main ()
{
  int n;
  qsort (values, 6, sizeof(int), compare);
  for (n=0; n<6; n++)
     printf ("%d ",values[n]);
  return 0;
}
第六章
  • 结构基本知识

结构是一个或多个变量的集合,这些变量可能为不同的类型。

struct point {
    int x;
    int y;
};
struct {...} x, y, z; //struct声明定义了一种数据类型,在标志结构成员表结束的右括号之后可以跟一个变量表,这与其他基本类型的变量声明是相同的。
int x, y, z; //本质是一样的。
struct point pt;
struct point maxpt = {320, 200};
printf("%d,%d", pt.x, pt.y);
struct rect {
    struct point pt1;
    struct point pt2;
};
struct rect scream;
scream.px1.x;
  • 结构与函数
struct point makepoint(int x, int y){ //参数名和结构成员同名不会引起冲突
    struct point temp;
    temp.x = x;
    temp.y = y;
    return temp;
}
  • 结构指针
struct point *pp; //定义pp为一个指向struct point类型对象的指针
如果pp指向一个point结构,那么*pp即为该结构,而(*pp).x和(*pp).y则是结构成员
struct point origin, *pp;
pp = &origin;
printf("%d,%d",(*pp).x, (*pp).y);
//p->结构成员(->指针使用)
printf("%d,%d",pp->x, pp->y);
struct rect r, *rp = &r;
//以下四个等价
r.pt1.x;
rp->pt1.x;
(r.pt1).x;
(rp->pt1).x;
  • 结构数组
struct point {
    int x;
    int y;
} points[10];
struct point points[10];

sizeof(对象) sizeof(类型名) 返回一个整型值(size_t),等于指定对象和类型占用的存储空间字节数

  • 自引用结构

常用于树结构

  • 表查找

哈希表

  • typedef
typedef int Length;
Length len, maxlen;
Length *lengths[];
typedef char *String;//将String定义为char*字符指针
String p;
  • 联合

和访问结构的方式一样,是一种“特殊的”结构

第七章&第八章

第七章讲输入/输出标准库,第八章讲Unix系统的接口,文件操作,与《UNIX环境高级编程》一书某些章节一样,在看这本书时再展开。

最后,分享几个别人的读书笔记

https://www.cnblogs.com/xkfz007/archive/2012/08/05/2623702.html

https://www.cnblogs.com/xkfz007/articles/2566424.html

链接

https://github.com/1326670425/TCPL

http://kissg.me/2016/07/10/notes-on-the-c-programming-language/

你可能感兴趣的:(《C程序设计语言》)