这是第九章的内容了。哈哈。看得比较慢拉。但是还是得看下去哈。这本书实在是写得太好了。
1. 声明本身还可以进一步分成三种情况:
(1)外部数组的声明。
(2)数组的定义(记住,定义是声明的一种特殊情况,它分配内存空间,并可能提供一个初始值)。
(3)函数参数的声明。
2. 所有作为函数参数的数组名总是可以通过编译器转换为指针。
3. 数组的声明就是数组,指针的声明就是指针,两者不能混淆。但在使用数组(在语句或者表达式中引用)时,数组总是可以写成指针形式,两者可以互换。
4. 对编译器而言,一个数组就是一个地址,一个指针就是一个地址的地址。“作为函数定义的形式参数”,指针和数组是一样的。
看一看到大量的作为函数参数的数组和指针,在这种情况下,两者是可以完全互换的。如:
char my_array[10];
char *my_ptr;
.......
i = strlen(my_array);
j = strlen(my_ptr);
i 和j是相等的。它们有且只发生在这一种特定的上下文的环境中,也就是它们作为一个函数调用的参数使用。
5 .在论数组和指针的相同和不同:
规则 1: “表达式中的数组名” 就是指针。
规则 2: C 语言把数组下标作为指针的偏移量。
规则 3: “作为函数参数的数组名” 等同于指针。
6. 编译器自动把下标的步长调整到数组元素的大小。如果整形数 的长度是4个字节,那么a[i+1]和a[i] 在内存中的距离就是4,(而不是1).
7. 在表达式中,指针和数组是可以互换的,因为它们在编译器里的形式都是指针,并且可以进行取下标操作,就像加法一样,取下标操作符的操作数是可以交换的(它并不在意操作数的先后顺序)。这就是为什么在一个a[10] 的声明中下面形式都是正确的:
a[6] = .....;
6[a] = .....;
8. 在给函数传递参数的时候,传递数组的时候,如果要拷贝整个数组,无论在时间上还是内存空间上的开销都可能是非常大的。而且在绝大部分情况下,其实并不需要整个数组的拷贝。所以:采用“所有的数组在作为参数传递时都转换为指向数组起始地址的指针,而其他的参数采用传值调用”的约定,就可以简化编译器。函数的返回值也不能是一个函数数组,而是指向数组或函数的指针。
9. 不能把一个数组赋值给另一个数组,因为数组作为一个整体不能成为赋值的对象。
10 . 如果元素的类型是指针,那么它们被初始化为NULL;如果元素的类型是float,那么它们被初始化为0.0.
11. 只有字符串常量才可以初始化指针数组。指针数组不能由非字符串类型直接初始化。:
int *weight[] = {
{ 1, 2,3 ,4, 5}, {6,7}, {8,9,10}
}; //这是无法编译成功的。
12. 如果想用这种方法对数组进行初始化,可以创建几个单独的数组,然后用这些数组名来初始化原先的数组。
int row _1[] = {1,2, 3,4,5,-1}; // -1 是行结束标志。
int row_2[] = {6,7,-1};
int row_3[] = {8,9,10,-1};
int *weight[] = {
row_1, row_2,row_3
};
下面是第十章的内容:《再论指针》
13. char *pea[23] 把pea声明为一个具有23个元素的数组,每个元素的类型是一个指向字符的指针(或者一个字符串——单纯从声明中无法区分两者)。
14. 只要有可能,尽量不要选择拷贝整个字符串的方法。如果需要从两个不同的数据结构访问它,拷贝一个指针比拷贝整个数组快得多,空间也节省很多。另外一个可能影响性能的因素就是拷贝会使字符串分配于内存中的不同的页面中。这就违背了局部引用的规则(一次读写的数据位于同一页面上),并导致更加频繁的页面交换。
15. 在C 语言中,任何一维数组均可以作为函数的实参。形参被改写为指向数组第一个元素的指针,所以需要一个约定来提示数组的长度: (1)增加一个额外的参数 ,表示元素的数据(argc就是这个作用)
(2)赋予数组最后一个元素一个特殊的值,提示它是数组尾部。这个特殊值必须不会作为正常的元素值在数组中出现。
16. 向函数中传递一个一维的数组:
(1)定义一个额外的参数,提示数组的行数。 (2)额外增加一个额外的行,行内所有元素的值都是不可能在数组正常元素中出现的,能够提示数组超出了范围。
17. 在C 语言中,没有办法向函数传递一个普通的多维数组。 因此必须提供了最左边一维以外的所有维的长度。这样就把实参限制为除最左边外所有维都必须与形参匹配的数组。
传递多位数组的方法: 方法一: my_function(int array[10][20]);
方法二: my_function(int array[][20]);
或者是:my_function(int (*array)[20]);
方法三: my_funciton(int **my_array);
注意:只有把二维数组改为一个指向向量的指针数组的前提下才可以这样做。
方法四:采用放弃多维数组的形式:char_array[row_size*i + j] = ......; (不推荐)
18. 千万要注意,不能从函数中返回一个指向函数的局部变量指针。
19 . NULL指针会导致printf函数崩溃。如:char *p = NULL; printf("%s",p);
会出现段错误。因为C标准规定%s说明符的参数必须是一个指向字符数组的指针。(NULL是一个指针,但是它并不指向一个字符数组。)所以调用将陷入“未定义行为”。
20 . 在实践中,不要把realloc()函数的返回值直接赋给字符指针,如果realloc函数失败,它会使该指针变成NULL,这样就无法对现有的标进行访问了。