《征服C指针》——读书笔记(2)

一、数组与指针

输出数组中每个元素的值(数组版):

#include <stdio.h>

int main(void)
{
	int i;
	int array[5];
	
	for(i = 0; i < 5; i++)
		array[i] = i;
	
	// 输出数组中每个元素的值(数组版)
	for(i = 0; i < 5; i++)
	{
		printf("array[%d]..%d\n", i, array[i]);
	}

	return 0;
}

输出数组中每个元素的值(指针版):

#include <stdio.h>

int main(void)
{
	int i;
	int *p;
	int array[5];
	
	for(i = 0; i < 5; i++)
		array[i] = i;
	
	// 输出数组中每个元素的值(指针版)
	for(i = 0, p = &array[0]; p < &array[5]; p++)
	{
		printf("array[%d]..%d\n", i++, *p);
	}

	return 0;
}

输出数组中每个元素的值(指针改进版):

#include <stdio.h>

int main(void)
{
	int i;
	int *p;
	int array[5];
	
	for(i = 0; i < 5; i++)
		array[i] = i;
	
	// 输出数组中每个元素的值(指针改进版)
	p = &array[0];
	for(i = 0; i < 5; i++)
	{
		printf("array[%d]..%d\n", i, *(p + i));
	}

	return 0;
}

以上3段代码实现的功能相同,无论是p++,还是*(p + i)其可读性都不强,a[i]的方式最容易理解,所以 抛弃指针运算的写法(?)


在指针改进版的例程中

p = &array[0]; 

其实也可以写成下面这样: 

p = array; 

对于这种写法,很多 C 语言的入门书籍是这样说明的: 在 C 中,如果在数组名后不加[ ],单独地只写数组名,那么此名称就表示“指向数组初始元素的指针”。 

在这里,我可以负责地告诉你,上面的说明是错误的。


将&array[0] 改写成 array,“改写版”的程序甚至可以写成下面这样:

p = array;
for(i = 0; i < 5; i++)
{
<span style="white-space:pre">	</span>printf("array[%d]..%d\n", i, *(p + i));
}
 

与下面这段代码进行比较

p = array;
for(i = 0; i < 5; i++)
{
	printf("array[%d]..%d\n", i, p[i]);
}

发现p[i]只不过是*(p + i)的简便写法罢了,除此之外,它毫无意义。

也就是说,存在 int array[5] 这样的声明的时候,“一旦后面不追加[ ],只写array”并不代表要使array具有指向数组第1个元素的指针的含义,无论加不加[ ],在表达式中,数组都可以被解读为指针


要点:

1. 表达式中,数组可以解读为“指向它的初始元素的指针”。尽管有3个小例外,但是这和在后面加不加[ ]没有关系。

2. p[i]是*(p + i)的简便写法。

    下标运算符[ ]原本就只有这种用法,它和数组无关。

3.p[i]可以写成i[p],但是不要写成这样。 


需要强调的是,认为[ ]和数组没有关系,这里的[ ]是指在表达式中出现的下标运算符[ ]。 声明中的[ ],还是表达数组的意思。

也就是说,声明中的[ ]和表达式中的[ ]意义完全不同。表达式中的*和声明中的*的意义也是完全不同的。这些现象使得 C 语言的声明在理解上变得更加扑朔迷离……

此外,如果将 a + b 改写成 b + a,表达式的意义没有发生改变,所以你可以将*(p + i)写成*(i + p)。其次,因为 p[i]是*(p + i)的简便写法,实际上它也可以写成 i[p]。 

引用数组元素的时候,通常我们使用 array[5]这样的写法。其实,就算你写成 5[array],还是可以正确地引用到你想要的元素。

可是,这种写法实在太另类了,它不能给我们带来任何好处。



二、将数组作为函数的参数进行传递

要点:

1.如果试图将数组作为函数参数进行传递,那就传递指向初始元素的指针

2.在迫不得已的情形下,如果你执意要将数组的副本作为参数进行传递,可以使用替代方法——将数组的所有元素整理成结构体的成员



三、声明函数形参的方法

在下面声明的形参,都具有相同的意义。 

int func(int *a);        /*写法1*/ 
int func(int a[]);       /*写法2*/ 
int func(int a[10]);     /*写法3*/ 

写法 2 和写法 3 是写法 1 的语法糖。


要点:

只有在声明函数形参时,数组的声明才可以被解读成指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值