第4章 数组和指针的常用方法

4.1 基本使用方法

4.1.1 以函数返回值之外的方式来返回值

大型程序中,经常需要通过返回值返回程序处理的状态(比如是否成功,如果失败,还需要返回失败的原因)。

如果将指针作为参数传递给函数,此后在函数内部对指针指向的对象填充内容,就可以从函数返回多个值。

#include<stdio.h>
void func(int *a,double *b) {
	*a=5;
	*b=3.5;
} 

int main() {
	int a;
	double b;
	func(&a,&b);
	printf("a..%d b..%f\n",a,b);
	return 0;
}
将指向int和double的指针传递给函数,此后在函数内部对这两个指针指向的变量设定值。

要点:如果需要通过函数返回值以外的方式返回值,将”指向T的指针“作为参数传递给函数。


4.1.2 将数组作为函数的参数传递

C语言中,数组是不能作为参数进行传递的。但可以通过传递指向数组初始元素的指针,使得在函数内部操作数组称为可能。

#include<stdio.h>
void func(int *array,int size) {
	int i;
	for(i=0;i<size;i++) {
		printf("array[%d]..%d\n",i,array[i]);
	}
} 

int main() {
	int array[]={1,2,3,4,5};
	func(array,sizeof(array)/sizeof(int));
	return 0;
}

要点:想要将类型T的数组作为参数进行传递,可以考虑传递”指向T的指针“。可是,作为被调用方是不知道数组的元素个数的,所以在必要条件下,需要使用其他方式进行参数传递。


4.1.3 可变长数组

通常C语言在编译时必须知道数组的元素个数,但也可以使用malloc()在运行时再为数组申请必要的内存区域。

这种数组称之为”可变长数组“。

#include<stdio.h>
#include<stdlib.h>
int main() {
	char buf[256];
	int size;
	int *variable_array;
	int i;
	
	printf("Input array size");
	fgets(buf,256,stdin);
	sscanf(buf,"%d",&size);
	
	variable_array=malloc(sizeof(int)*size);
	
	for(i=0;i<size;i++) {
		variable_array[i]=i;
	}
	for(i=0;i<size;i++) {
		printf("variable_array[%d]..%d\n",i,variable_array[i]);
	}
	
	
	return 0;
}

必须注意,在使用malloc()实现可变长数组的时候,程序员必须自己来管理数组的元素个数。


要点:在需要获得类型T的可变长数组时,可以使用malloc()来动态地给”指向T的指针“分配内存区域。但此时需要程序员自己对数组的元素个数进行管理。


补充:Java中的数组只能使用内存堆区域。Java的数组和C中使用的malloc()分配的数组,有决定性的不同,Java的数组是知道自身的长度的。此外,尽管Java的数组是保存在堆中,但却不能改变长度,没有类似于realloc()的函数。


4.2 组合使用

4.2.1 可变长数组的数组 P166~P172

4.2.2 可变长数组的可变长数组 P172~P174

4.2.3 命令行参数

对于main()函数,标准中指出必须要写出以下两种方式之一:

int main(void);、int main(int argc,char *argv[]);

正常使用第一种形式,如果使用第二种形式,可以取得命令行参数。如在UNIX中的cat命令-用于输出文件的内容。 cat hoge.txt (命令名后是想要输出的文件名)

如果像cat hoge.txt piyo.txt 输出就是将hoge.txt 和piyo.txt两个文件的内容连接后所得的结果。


对于第二种形式,其实可以和下面这种形式是完全一样的。

int main(int argc,char **argv);

argv[0]保存了命令名自身。在程序输出错误提示信息时,或者需要通过命令名称改变程序的行为时,会经常使用arg[0]。

argc保存了参数的个数(包含了arg[0])。实际上,从ANSI C之后,会保证argv[argc]肯定为NULL,所以完全可以没有argc。


4.2.4 通过参数返回指针

要点:异常处理中使用goto,反而让程序更加简洁。

C++/java中具备异常处理机制的语言,可以不用goto、在C中也有setjmp()/longjmp(),使用它们也能达到相似的效果。


4.2.5 将多维数组作为函数的参数传递

#include<stdio.h>
#include<stdlib.h>
void func(int (*hoge)[3]) {
	int i,j;
	for(i=0;i<4;i++) {
		for(j=0;j<3;j++) {
			printf("%d ",hoge[i][j]);
		}
		putchar('\n');
	}
}

int main(void) {
	int hoge[][3]={
					{1,2,3},
					{4,5,6},
					{4,5,6},
					{7,8,9},
					{10,11,12},
					};
	func(hoge);
	
	return 0;
}


4.2.6 数组的可变长数组
4.2.7 考虑使用结构体


补充:Java和C一样不存在多维数组,也是使用数组的数组来实现多维数组。但是Java和C不同的是,Java的数组都是指针,所以所谓的"数组的数组"其实是”指向数组的指针的数组“。

Java中的类(相当于C中的结构体)也是保存在堆中的,并且只能利用指针进行操作。因此Java中没有类似C中"结构体数组"这样对象。

阻碍Java程序快速执行的最大原因是Java过多使用了堆操作。

C++的对象可以不通过指针,而是通过实体来操作。为实现这个特性,C++使用了带参数的构造方法以及继承的概念,导致C++编程变得非常复杂。


4.3 违反标准的技巧

4.3.1 可变长结构体
4.3.2 从1开始的数组

C语言中,对指向超出数组范围以外的指针,除非它指向”最后元素的下一个元素“,其他情形都属于未定义。

补充:指针可以指到数组的最后元素的下一个元素。

for(p=&array[0];p<&array[SPAN];p++)
这里没有使用循环计数器,而是使用指针遍历数组的各元素。当循环到达终点时,p指向&array[SPAN],也就是array的最后元素的下一个元素。

只是为了照顾以前写的代码,标准才允许指针可以指到数组的”最后元素的下一个元素“。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值