《C专家编程》笔记第四、九、十章--论数组和指针

381 阅读4分钟

前言

不知作者是何意,第四章讲了数组和指针,然后跳了几章后,再第九章和第十章又讲了数组和指针,我认为这三章连起来读,会有很好的效果,所以本次笔记也是把第四章,第九章和第十章的内容统一记录。

笔记

P84

  这部分是第四章的重点,用书中的小标题可以概括本章的核心问题——数组和指针是如何访问的。 接下来我们用两个书中的例子,就可以搞清楚这个问题,并对数组和指针有了基础的了解。   首先来看数组是如何访问的:

       char a[9] = "abcdefgh";
       c = a[i];

从定义可知,a是一个包含9个元素的字符数组,然后对数组a的第i个元素进行引用。用书中原话对编译器执行这句语句时进行的操作进行解释。

这两个声明都提示 a 是一个数组,也就是一个内存地址,数组内的字符可以从这个地址找到。编译器不需要知道数组总共有多长,因为它只产生偏离起始地址的偏移地址。

再来看编译器是如何访问指针的:

     char* p = "abcsefgh";
     c = p[i]; 

同样用书中的话进行解释:

编译器符号表具有一个P,地址为4624
  运行时步骤1:取地址4624的内容,即5081
  运行时步骤2:取得i的值,并把它与5081相加。
  运行时步骤3:取地址[5081+i]的内容。

  上面的4624,5081都是为了说明而随便举的例子,真实情况应该是相应的地址。
  综上所述,数组和指针在访问时的主要区别就在于,前者是直接访问,数组名就是数组中存放第一个元素的地址;后者是间接访问,指针名也是一个地址,不过存放的内容是指针指向内容的首地址,所以属于间接访问。

P87

  数组和指针都可以在它定义中用字符串常量进行初始化。初始化指针时所创建的字符串常量被定义为只读,也就是不能修改,但由字符串常量初始化的数组是可以修改的。

P209

数组和指针的可交换性总结:
1、用a[i]这样的形式对数组进行访问总是被编译器“改写”或理解为像*(a+i)这样的指针访问。
2、指针始终是指针。它决不能改写成数组。你可以使用下标形式访问指针。
3、在作为函数参数时,一个数组的声明可以看成是一个指针,在定义时可以把定义成数组形式,也可以把它定义成指针形式。
4、在其他所有情况下,定义和声明必须匹配。

P225

数组和指针参数是如何被编译器修改的?

"数组名被改写成一个指针参数"规则并不是递归定义的。 数组的数组会被改写成“数组的指针”,而不是指针的指针。

  • 实参char c[8][10]; 所匹配的形式参数char (*)[10];
  • 实参char *c[15]; 所匹配的形式参数char **c;
  • 实参char (*c)[64]; 所匹配的形式参数char (*c)[64];
  • 实参char **c; 所匹配的形式参数char **c;

P236

在C语言数组的定义的时候,数组长度一定是固定的,但有时我们需要根据实际情况来调整数组长度的大小,一种解决方法就是直接声明一个很大的数组,但这样非常浪费内存,另一种方法就是使用动态数组,让程序在运行时确定数组的大小。

当需要在动态表中增长一个项目时,可以进行如下操作:
1、对表进行检查,看看他是否真的已满。
2、如果已满,使用realloc()函数扩展长度。并进行检查,确保realloc()操作成功。
3、在表中增加所需要的项目。
用C代码表示,大致如下:

    int currnt_element = 0;
    int total_element = 128;
    char *dynamic = malloc(total_element);
    void add_element(char c){
        if(current_element == total_element - 1){
            total_element *= 2;
            dynamic = (char*)realloc(total_element);
            if(dynamic == NULL) error("coundn`t expand the table ");
        }
        current_element++;
        dynamic[crrent_element] = c;
    }

在实践中,不要把realloc()函数的返回值直接付给字符指针。如果realloc() 函数失败,它会使该指针的值变成NULL,这样就无法对现有的表进行访问。