浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记

2.1.1.2 计算机和编程语言:计算机的思维方式

程序的执行

  • 解释:借助一个程序,那个程序能试图理解你的程序,然后按照你的要求执行。
  • 编译:借助一个程序,就像一个翻译,把你的程序翻译成计算机真正能懂的语言——机器语言——写的程序,然后,这个机器语言写的程序就能直接执行了。

11.2.1.3 变量:变量赋值与初始化

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第1张图片

如果变量没有初始化,就直接拿到右边去用,会出现什么呢?

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第2张图片

得到了一个非常奇怪的结果,这是因为,在内存当中,我们有一个变量 i 我们没有给它一个初始值,那么,它正好在内存当中,在什么地方,那个地方原本有一些什么样的值在里头,它就是那个值了。

12.2.1.4 变量:变量输入

读整数

  • scanf("%d", &price);
  • 要求scanf这个函数读入下一个整数,读到的结果赋值给变量price。

scanf和printf中,f表示format格式化的意思。

13.2.1.5 变量:常量VS变量

常量(C99)

  • int change = 100 - price;
  • 固定不变的数,是常数。直接写在程序里,我们称作直接量(literal)。
  • 更好的方式,是定义一个常量:const int AMOUNT = 100
#include 

int main()
{
    const int AMOUNT = 100;
    int price = 0;

    printf("请输入金额(元):");
    scanf("%d", &price);

    int change = AMOUNT - price;
    printf("找您%d元。\n", change);

    return 0;
}

const(C99)

  • const是一个修饰符,加在int的前面,用来给这个变量加上一个const(不变的)的属性。这个const的属性表示这个变量的值一旦初始化,就不能再修改了。
  • int change = AMOUNT - price;
  • 如果你试图对常量做修改,把它放在赋值运算符的左边,就会被编译器发现,指出为一个错误。

14.2.1.6 变量:浮点数

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第3张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第4张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第5张图片

%lf对应double。

16.2.2.2 表达式:运算符优先级

注意这里优先级为1的单目运算符+-

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第6张图片

注意,a=6这个式子本身,是有结果的,也就是6。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第7张图片

17.2.2.3 表达式:交换变量

视频中4分20秒开始出现Dev C++断点调试的使用方法。

20.3.0.1 编程练习解析:PAT再解释

视频中5分30秒开始,出现了对scanf的讲解。

出现在scanf格式字符串里面的东西,是它一定要你输入的东西,而不是它会给你看的东西。

28.3.2.1 分支:嵌套的if-else

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第8张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第9张图片

(学习笔记:能用大括号就用大括号,避免歧义。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第10张图片

29.3.2.2 分支:级联的if-else if

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第11张图片

30.3.2.3 分支:if-else的常见错误

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第12张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第13张图片

31.3.2.4 分支:多路分支

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第14张图片

(以下代码利用了switch-case的某个特性)

34.4.1.3 循环:do-while循环

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第15张图片

(注意:while结尾要有分号)

35.4.2.1 循环应用:循环计算

(计算之前先保存原始的值,后面可能有用。)

40.5.1.2 第三种循环:循环的计算和选择

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第16张图片

41.5.2.1 循环控制:循环控制

(判断素数)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第17张图片

(上面的代码中,设置一个标志位的写法,我认为值得借鉴。)

(判断素数的另一种写法。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第18张图片

43.5.2.3 循环控制:从嵌套的循环中跳出

#include 

int main()
{
    int x;
    int one, two, five;
    int exit = 0;

    scanf("%d", &x);
    for (one=1; one<x*10; one++)
    {
        for (two=1; two<x*10/2; two++)
        {
            for (five=1; five<x*10/5; five++)
            {
                if (one + tw0*2 + five*5 == x*10)
                    {
                        printf("可以用%d个1角加%d个5角得到%d元\n",
                            one, two, five, x);
                        exit = 1;
                        break;
                    }
            }
            if (exit == 1) break;
        }
        if (exit == 1) break;
    }
}

(
我主要对这里的先设置一个标志int exit = 0;,然后满足某种条件后,改变标志exit = 1,进而改变程序控制流程的写法,感兴趣。
)

45.5.3.2 循环应用:整数分解

(这一段的视频值得重新一看,整数正序分解,因为C 语言中没有趁手的工具,所以这里实现起来略繁琐。)

46.5.3.3 循环应用:求最大公约数

辗转相除法求最大公约数

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第19张图片

48.6.0.2 编程练习解析:编程练习解析4-1

(水仙花数编程实现,值得一看)

49.6.0.3 编程练习解析4-2:九九乘法表

50.6.0.4 编程练习解析4-3:统计素数求和

(关键词:素数、质数)

52.6.0.6 编程练习解析5-0:n项求和

每一项的分子是前一项分子与分母的和,分母是前一项的分子。

(下面的代码值得一看)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第20张图片

54.6.1.1 数据类型:数据类型

sizeof

  • 是一个运算符,给出某个类型或变量在内存中所占据的字节数
  • sizeof(int)
  • sizeof(i)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第21张图片

55.6.1.2 数据类型:整数类型

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第22张图片

整数

  • char:1字节(8比特)
  • short:2字节
  • int:取决于编译器(CPU),通常的意义是“1个字”
  • long:取决于编译器(CPU),通常的意义是“1个字”
  • long long:8字节

当我们在说1台计算机的字长的时候,我们指的是寄存器是多少宽的,也就是说,这个寄存器是几个bit的。比如说,当我们说寄存器是32个bit的,每一个寄存器可以表达32个bit的数据,同时也是在说,CPU和RAM之间在总线上传递数据的时候,每一次的传递是32个bit,也就是说,当要从内存RAM取数据到CPU里面去,每一次就会要取32个bit。

除了32,现在更常见的是64个bit。

字长在C语言中,反映为int。int表达的是1个寄存器的大小。所以,在不同的平台、CPU上面,int会不一样大。

56.6.1.3 数据类型:整数的内部表达

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第23张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第24张图片

所以,为什么我们要在计算机的内部使用补码呢?

最大的好处就是,如果你有了一个补码,你用补码来表示这个-1,那么,当你在做加法的时候,你不需要根据条件,去变换,把加+变成减-,你直接拿它去做普通的二进制的加法,你就会得到你想要的那个结果。

57.6.1.4 数据类型:整数的范围

整数越界

整数是以纯二进制方式进行计算的,所以:
- 11111111 + 1 –> 100000000 –> 0
- 01111111 + 1 –> 10000000 –> -128(这里我存在疑问)
- 10000000 + 1 –> 01111111 –> 127

下面的代码似乎可以解答我的疑问:

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第25张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第26张图片

-2^(32-1) —— 2^(32-1)-1

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第27张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第28张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第29张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第30张图片

(关键词:无符号数、unsigned
这整段视频建议重新细看、加强理解。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第31张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第32张图片

58.6.1.5 数据类型:整数的格式化

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第33张图片

(如下的代码,建议看视频的详细解释)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第34张图片

59.6.1.6 数据类型:选择整数类型

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第35张图片

60.6.1.7 数据类型:浮点类型

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第36张图片

(inf:正负的无穷大
nan:表示不是一个有效的数字
这段视频建议再去详细看。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第37张图片

科学计数法

#include 

int main()
{
    double ff = 1234.56789;
    printf("%e,%f\n", ff, ff);

    return 0;
}

输出:

1234568e+03,1234.567890

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第38张图片

#include 

int main()
{
    double ff = 1E-10;
    printf("%E,%f\n", ff,ff);

    return 0;
}

输出:

1.000000E-10,0.000000

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第39张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第40张图片

61.6.1.8 数据类型:浮点的范围与精度

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第41张图片

#include 

int main()
{
        printf("%f\n", 12.0/0.0);
        printf("%f\n", -12.0/0.0);
        printf("%f\n", 0.0/0.0);

        return 0;
}
$ gcc q.c
$ ./a.out
inf
-inf
-nan

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第42张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第43张图片

62.6.1.9 数据类型:字符类型

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第44张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第45张图片

63.6.1.10 数据类型:逃逸字符

(即转义字符)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第46张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第47张图片

64.6.1.11 数据类型:类型转换

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第48张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第49张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第50张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第51张图片

65.6.2.1 其他运算:逻辑类型

bool

  • #include
  • 之后就可以使用bool和true、false。

67.6.2.3 其他运算:条件运算与逗号运算

条件运算符

  • count = (count > 20) ? count - 10 : count + 10
  • 条件、条件满足时的值和条件不满足时的值。

69.7.1.2 函数的定义和使用:函数的定义和调用

(8分01秒开始出现了“单步进入”,讲解了调用函数时,进入函数内部、单步调试)

71.7.2.1 函数的参数和变量:函数原型

函数的先后关系

void sum(int begin, int end)
{
    int i;
    int sum = 0;
    for (i=begin; i<=end; i++)
    {
        sum += i;
    }
    printf("%d到%d的和是%的\n", begin, end, sum)
}

int main()
{
    sum(1,10);
    sum(20,30);
    sum(35,45);

    return 0;
}

像这样把sum()写在上面,是因为:

  • C的编译器自上而下顺序分析你的代码;
  • 在看到sum(1,10)的时候,它需要知道sum()的样子;
  • 也就是sum()要几个参数,每个参数的类型如何,返回什么类型。
void sum(int begin, int end);   // 声明。这里是函数原型

int main()
{
    sum(1,10);
    sum(20,30);
    sum(35,45);

    return 0;
}

void sum(int begin, int end)    // 定义。
{
    int i;
    int sum = 0;
    for (i=begin; i<=end; i++)
    {
        sum += i;
    }
    printf("%d到%d的和是%的\n", begin, end, sum)
}

72.7.2.2 函数的参数和变量:参数传递

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第52张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第53张图片

C语言在调用函数时,只能传值给函数。

当我们在main()函数中,做swap(a,b)的时候,是把a的值5交给了swap里的a、把b的值6交给了swap里的b。swap里的a、b,与main里的a、b完全没有任何关系的。

我们在swap里面,对a、b做的任何事情,是swap里的参数a、b的事情,和main的a、b没有任何关系。如上的代码,不能交换a、b的值。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第54张图片

73.7.2.3 函数的参数和变量:本地变量(局部变量)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第55张图片

(关键词:本地变量,也叫做局部变量,因为英文是local,可翻译为本地或局部。
)

也有的地方把它叫做自动变量,把它叫做自动变量是和我们后面讲的一件事情有关系,它的生存期和作用域的关系,把它叫做自动变量是因为,它的生存期是自动的。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第56张图片

(这一段,建议借助视频讲解和在Dev C++编译器中断点调试,可以辅助加强理解context等概念的含义。

关键词:生存期、作用域
从1分59秒开始看。
从4分09秒开始看。)

本地变量的规则

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第57张图片

(整段视频都值得重新仔细看,介绍了作用域、生存期,可以结合Python的LEGB同时理解。

特别是8分39秒开始的地方,依次介绍了类似嵌套作用域、变量掩盖之类的概念。)

76.8.1.2 数组:数组的使用

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第58张图片

在内存中,数组的单元是依次排列的,而且是紧密依次排列的。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第59张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第60张图片

77.8.1.3 数组:数组的例子

通常来说,用到数组的程序,都需要这么一些环节。

78.8.2.1 数组运算:数组运算

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第61张图片

(以下值得一看)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第62张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第63张图片

79.8.2.2 数组运算:数组例子

(判断素数、质数)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第64张图片

(求解素数的另外一种思路的算法。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第65张图片

(伪代码)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第66张图片

80.8.2.3 数组运算:二维数组

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第67张图片

81.9.1.1 指针:取地址运算

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第68张图片

为什么变量会有地址?

因为 C 语言的变量,是放在内存里的。每 1 个变量,比如说 int ,可能是 4 个字节,在内存中要占一定的地方,放在某个地方,就有 1 个地址。 & 运算符就是把地址拿出来。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第69张图片

(整段视频都值得重新看,
特别是6分38秒开始的,
关键词:C语言的内存模型、变量的地址、内存中的堆栈stack、自顶向下、分配变量。
)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第70张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第71张图片

#include 

int main(void)
{
        int a[10];

        printf("%p\n", &a);
        printf("%p\n", a);
        printf("%p\n", &a[0]);
        printf("%p\n", &a[1]);

        return 0;
}

输出:

$ gcc q.c
$ ./a.out
0x7ffe025df0d0
0x7ffe025df0d0
0x7ffe025df0d0
0x7ffe025df0d4

82.9.1.2 指针:指针

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第72张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第73张图片

(最后2行,p为int型指针,q为int型、不是指针。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第74张图片

当我们说, p 指向了 i,实际的意思是,p 的值是变量 i 的地址。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第75张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第76张图片

#include 

void f(int *p);
void g(int k);

int main(void)
{
        int i = 6;
        printf("&i=%p\n", &i);
        f(&i);
        g(i);
        return 0;
}

void f(int *p)
{
        printf(" p=%p\n", p);
        printf("*p=%d\n", *p);
}

void g(int k)
{
        printf("k=%d\n", k);
}

输出:

$ gcc w.c
$ ./a.out
&i=0x7ffd4447a5d4
 p=0x7ffd4447a5d4
*p=6
k=6

这就意味着,通过 *p 这个指针,我们访问到了 p 所指的 int i 里面的值。

增加一行代码 *p = 26;

#include 

void f(int *p);
void g(int k);

int main(void)
{
        int i = 6;
        printf("&i=%p\n", &i);
        f(&i);
        g(i);
        return 0;
}

void f(int *p)
{
        printf(" p=%p\n", p);
        printf("*p=%d\n", *p);
        *p = 26;
}

void g(int k)
{
        printf("k=%d\n", k);
}

输出:

$ gcc w.c
$ ./a.out
&i=0x7ffd8ecfb624
 p=0x7ffd8ecfb624
*p=6
k=26

k=26 意味着,在经历了 f 函数的调用了之后, i 的值被改了。

地址值 &i 被传进了函数 f(int *p),这里,仍然是值的传递,因为传进来的是地址,所以,通过这个地址,在函数内部,可以以这种方式,访问到外面的 i 变量。

因为 p 的值,就是 i 的地址。 *p 就代表了 i 。

当我们做 *p = 26 这个运算的时候,我们实际做的事情,是对 i 做的。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第77张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第78张图片

83.9.1.3 指针:指针的使用

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第79张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第80张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第81张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第82张图片

84.9.1.4 指针:指针与数组

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第83张图片

(函数参数里的数组是指针。
从视频0分59秒开始看起)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第84张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第85张图片

(“*arar[]在函数参数表中出现,是等价的”)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第86张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第87张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第88张图片

(const 常量)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第89张图片

85.9.1.5 指针:指针与const

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第90张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第91张图片

上图。如果指针是const,比如int * const q = &i;,在这种情况下,q这个指针是const,它的意思是说,q的值不能被改变,什么是q的值?就是i的地址,就是q指向了i这个事实不能被改变,也就是q不能再指向别人了,它们之间的关系是永久的。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第92张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第93张图片

(对上图和上上图的一点说明:)
p可以指向别人,i可以被赋以别的值,但是通过p去修改i就不可以。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第94张图片

如果const在*前面,那么,表示它所指的东西不能被修改;
如果const在*后面,那么,表示指针不能被修改;

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第95张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第96张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第97张图片

86.9.2.1 指针运算:指针运算

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第98张图片

当我们给一个指针加1的时候,它不是在地址值上加1,它在地址值上加一个sizeof(那个指针所指的类型)

所以对指针做一个加1的动作,意味着,我们要把它移到下一个单元去。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第99张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第100张图片

(当做两个指针相减的时候,它给你的是两个地址的差除以sizeof(它的类型),也就是,在这两个地址之间,有几个这样类型的东西在,或者说,能放几个这样类型的东西。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第101张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第102张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第103张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第104张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第105张图片

87.9.2.2 指针运算:动态内存分配

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第106张图片

(0分52秒开始,略为完整地介绍了动态内存分配malloc、内存释放free()。

第12行:
malloc返回的结果是是void *,而a是int*,所以我们还要类型转换一下。(在前面加上(int*))。
)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第107张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第108张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第109张图片

(第8行:每次申请100兆的空间,然后把申请到的空间,交给p,(p=malloc(100*1024*1024))中,对p做了一个赋值。赋值也是个表达式,有个结果,结果就是p得到的malloc的那个结果。

while ( (p=malloc(100*1024*1024)) ){
    cnt++;
}

这样的代码同时做了2件事情:
1.把malloc的结果赋给了p这个变量;
2.要让p得到的这个值,拿来做while的条件。

如果p得到的地址不是0,那就意味着它得到了一个有效的地址,那么,我们循环要继续,要让cnt去加加。
如果它得到的地址是0,那么while就要退出来。
)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第110张图片

(着重:首地址)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第111张图片

88.10.1.1 字符串:字符串

(在字符数组的最后一个元素,使用'\0')

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第112张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第113张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第114张图片

89.10.1.2 字符串:字符串变量

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第115张图片

(0分28秒开始。
关键词:程序的代码段、只读、保护机制。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第116张图片

90.10.1.3 字符串:字符串的输入输出

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第117张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第118张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第119张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第120张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第121张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第122张图片

91.10.1.4 字符串:字符串数组,以及程序参数

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第123张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第124张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第125张图片

92.10.2.1 字符串函数:单字符输入输出

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第126张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第127张图片

93.10.2.3 字符串函数: 字符串函数 strlen

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第128张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第129张图片

(作为参数,数组的形式和指针的形式是一样的,因为,数组传进去,也是指针,所以,我们在这里全部用指针的形式来表达了。)

size_t strlen(const char *s)的参数中,const char *s的前面有 1 个const,含义是,希望函数strlen()不修改传进去数组char *s

94.10.2.3 字符串函数:字符串函数strcmp

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第130张图片

(4分01秒开始,对strcmp的重新实现,值得一看。
包括数组实现和指针实现。
)

95.10.2.4 字符串函数: 字符串函数 strcpy

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第131张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第132张图片

(5分20秒开始,分析并重新实现了strcpy,有数组、指针版本。)

96.10.2.5 字符串函数strcat

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第133张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第134张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第135张图片

97.10.2.6 字符串函数:字符串搜索函数

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第136张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第137张图片

98.11.1.1 枚举:枚举

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第138张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第139张图片

99.11.2.1 结构:结构类型

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第140张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第141张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第142张图片

(上 面的代码中,main函数外的struct date { sth. }是在声明一种新的结构类型,main函数内的struct date today = sth.是在定义这种结构类型的一个结构变量。
)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第143张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第144张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第145张图片

(数组变量的名字,就是数组的地址。)

100.11.2.2 结构:结构:结构与函数

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第146张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第147张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第148张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第149张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第150张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第151张图片

101.11.2.3 结构:结构中的结构

(结构数组)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第152张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第153张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第154张图片

102.11.3.1 联合:类型定义

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第155张图片

(上面,Date是别名。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第156张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第157张图片

103.11.3.2 联合: 联合

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第158张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第159张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第160张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第161张图片

104.12.1.1 全局变量:全局变量

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第162张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第163张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第164张图片

105.12.1.2 全局变量: 静态本地变量

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第165张图片

#include 

int f(void);

int gAll = 12;

int main(int argc, char const *argv[])
{
        f();
        f();
        f();
        return 0;
}

int f(void)
{
        static int all = 1;
        printf("in %s all=%d\n", __func__, all);
        all += 2;
        printf("agn in %s all=%d\n", __func__, all);
        return all;
}

输出:

$ gcc q.c
$ ./a.out
in f all=1
agn in f all=3
in f all=3
agn in f all=5
in f all=5
agn in f all=7

(
个人理解:

这里的 静态本地变量 ,让我联想起了 Python 中的 生成器yield

有时间一定要去读 《 Python 源码分析》,了解下生成器的内部实现。
)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第166张图片

106.12.1.3 全局变量: 后记

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第167张图片

  • 返回本地变量的地址是危险的

如果有 1 个函数,你要让它返回 1 个指针,那么,你如果返回的是本地变量的地址,这是危险的。
因为一旦离开这个函数,本地变量就不存在了。

#include 

int* f(void);
void g(void);

int main(int argc, char const *argv[])
{
        int *p = f();
        printf("*p=%d\n", *p);
        g();
        printf("*p=%d\n", *p);

        return 0;
}

int* f(void)
{
        int i=12;
        return &i;
}

void g(void)
{
        int k = 24;
        printf("k=%d\n", k);
}

我的输出:

$ gcc q.c
q.c: In function ‘f’:
q.c:19:9: warning: function returns address of local variable [-Wreturn-local-addr]
  return &i;
         ^
$ ./a.out
Segmentation fault (core dumped)

视频中的输出:

。。。
1 warning generated.
*p=12
k=24
*p=24

*p 又变成 24 了,但这个过程中,没有人对 *pi 做任何事情,但是 p 所指的那个地方却变成了 24 了。

你可以自己改一点这里的程序,如果在 f 函数里打印出 i 的地址,在 g 函数里打印出 k 的地址,你会发现它们是一样的。

返回 1 个本地变量的地址,让外面的程序继续使用它是有风险的。因为这个函数结束以后,那个本地变量的地址会被继续分配给别人去使用的。

  • 返回全局变量或静态本地变量的地址是安全的

因为,全局变量或静态本地变量的地址和函数没关系,它们是全局生存期的。

  • 返回在函数内 malloc 的内存是安全的,但是容易造成问题

  • 最好的做法是返回传入的指针

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第168张图片

107.12.2.1 编译预处理和宏: 宏定义

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第169张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第170张图片

#include 

#define PI 3.14159
#define FORMAT "%f\n"
#define PI2 2*PI // pi * 2
#define PRT printf("%f ", PI); \
            printf("%f\n", PI2)

int main(int argc, char const *argv[])
{
        printf(FORMAT, PI2*3.0);
        PRT;
        return 0;
}

输出:

$ gcc q.c
$ ./a.out
18.849540
3.141590 6.283180

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第171张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第172张图片

108.12.2.2 编译预处理和宏: 带参数的宏

像函数的宏

  • #define cube(x) ((x)*(x)*(x))
  • 宏可以带参数

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第173张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第174张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第175张图片

宏定义的结尾不要加上分号 ;

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第176张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第177张图片

109.12.3.1 大程序结构: 多个源代码文件

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第178张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第179张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第180张图片

110.12.3.2 大程序文件: 头文件

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第181张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第182张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第183张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第184张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第185张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第186张图片

111.12.3.3 大程序结构: 声明

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第187张图片

  • 定义时产生代码的东西

比如说函数、全局变量。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第188张图片

在头文件中方的不是声明,而是定义,会造成问题。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第189张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第190张图片

112.13.1.1 文件: 格式化输入输出

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第191张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第192张图片

#include 

int main(int argc, char const *argv[])
{
        printf("%9d\n", 123);
        printf("%-9d\n", 123);
        printf("%+9d\n", 123);
        printf("%+-9d\n", 123);
        printf("%-+9d\n", 123);
        printf("%-+9d\n", -123);
        printf("%-9d\n", -123);
        printf("%09d\n", 123);

        return 0;
}

输出:

#include 

int main(int argc, char const *argv[])
{
        printf("%9d\n", 123);
        printf("%-9d\n", 123);
        printf("%+9d\n", 123);
        printf("%+-9d\n", 123);
        printf("%-+9d\n", 123);
        printf("%-+9d\n", -123);
        printf("%-9d\n", -123);
        printf("%09d\n", 123);

        return 0;
}

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第193张图片

#include 

int main(int argc, char const *argv[])
{
        printf("%9.2f\n", 123.0);

        return 0;
}

输出:

$ gcc q.c
$ ./a.out
   123.00

printf("%9.2f\n", 123.0);中,9.2f的含义是,输出 1 个浮点数,后面是 2 位小数,前面的空位、整数位、小数点位加上小数位,一共是 9 位。

#include 

int main(int argc, char const *argv[])
{
        printf("%*d\n", 6, 123);

        return 0;
}

输出:

$ gcc q.c
$ ./a.out
   123

printf("%*d\n", 6, 123);* 意思是, 6 是用来满足这个 * 的, 6 会被填到 * 里面去; 123 是用来满足这个 d 的。

所以,输出包括前面的 3 个空格加后面的 3 位数,总共占据 6 个位置。

#include 

int main(int argc, char const *argv[])
{
        int num;
        printf("%drf%n\n", 12345, &num);
        printf("%d\n", num);

        return 0;
}

输出:

$ gcc q.c
$ ./a.out
12345rf
7

printf("%drf%n\n", 12345, &num);中, %n 的含义是,当 printf 执行到这个地方的时候,已经输出了多少个字符,然后填到 &num 指针所指的那个变量里面去。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第194张图片

#include 

int main(int argc, char const *argv[])
{
        int num;
        scanf("%*d%d", &num);
        printf("%d\n", num);
        return 0;
}

输出:

$ gcc q.c -o test
$ ./test
123 345
345

说明:把前面的 123 跳过,然后读到了 345 。 * 的意思是跳过。

#include 

int main(int argc, char const *argv[])
{
        int num;
        scanf("%i", &num);
        printf("%d\n", num);
        return 0;
}

输出:

$ gcc q.c -o test
$ ./test
123
123
$ ./test
0x12
18
$ ./test
012
10

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第195张图片

113.13.1.2 文件: 文件输入输出

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第196张图片

$ gcc q.c -o test
$ ./test
12345
12345
$ ./test > 12.out
12345
$ cat 12.out
12345
$ cat > 12.in
12345(备注:这里可能需要输入 Ctrl + D 终止。)
$ cat 12.in
12345
$ ./test < 12.in
12345
$ ./test < 12.in > 12.out
$ cat 12.out
12345

这是叫做程序运行时的重定向。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第197张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第198张图片

#include 

int main(int argc, char const *argv[])
{
        FILE *fp = fopen("12.in", "r");
        if ( fp ) {
                int num;
                fscanf(fp, "%d", &num);
                printf("%d\n", num);
                fclose(fp);
        } else {
                printf("无法打开文件\n");
        }

        return 0;
}
$ gcc q.c -o test
$ ./test
12345
$ rm 12.in
$ ./test
无法打开文件

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第199张图片

114.13.1.3 文件: 二进制文件

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第200张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第201张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第202张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第203张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第204张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第205张图片

(视频中,这里有一段代码,建议看视频。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第206张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第207张图片

115.13.2.1 位运算: 按位运算

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第208张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第209张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第210张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第211张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第212张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第213张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第214张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第215张图片

(视频中,有代码,建议看视频。)

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第216张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第217张图片

对 1 个数,做 2 次异或,就翻回去了。

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第218张图片

116.13.2.2 位运算:移位运算

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第219张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第220张图片

117.13.2.3 位运算:位运算例子

118.13.2.4 位运算: 位段

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第221张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第222张图片

119.14.1.1 可变数组: 可变数组

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第223张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第224张图片

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第225张图片

120.14.1.2 可变数组:可变数组的数据访问

121.14.1.3 可变数组:可变数组的自动增长

122.14.2.1 链表:可变数组的缺陷

123.14.2.2 链表: 链表

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第226张图片

#include _NODE_H_
#define _NODE_H_

typedef struct _node {
    int value;
    struct _node *next;
} Node;

# endif

124.14.2.3 链表:链表的函数

125.14.2.4 链表:链表的搜索

126.14.2.5 链表:链表的删除

浙大版《C语言程序设计(第3版)》 - 翁恺 - 学习笔记_第227张图片

127.14.2.6 链表:链表的清除


断点调试

Dev C++的断点调试

参考文献:
1. C语言 - 翁恺 - 浙江大学。

你可能感兴趣的:(编程语言,C语言)