码迷,mamicode.com
首页 > 编程语言 > 详细

C语言中值得深入知识点----数组做函数参数、数组名a与&a区别、数组名a的"数据类型"

时间:2016-07-13 16:34:13      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

1、数组作为函数参数

C语言中,数组做为函数的参数,退化为指针。数组作为参数传给函数时,传的是指针而不是数组,传递的是数组的首元素的地址。这里我们以将以整形变量排序来讲解。

void sortArray(int a[] ,int num )以及void sortArray(int a[100] ,int num )都可以用void sortArray(int *a ,int num )表示。一般来说函数参数如果为数组,可以有两个参数,一个是数组名,一个是数组长度。对于排序而已,一般是要知道给定数组的首元素的地址,即需要排序的数组在内存中的起始地址,同时还需给定待排序的数据个数。

       这里我们采用简单的冒泡排序,模块代码如下:

 /*2016-7-12 Jason Gel */
void sortArray(int *a ,int num )
{
	int i ,j ,temp;
	for(i =0 ;i <num;i++)              //外层:每次选定出需要排序的一个元素,依次向后
	{
		for( j=i+1; j<num; j++ )  //内层:外层选定的一个元素与其后所有元素依次比较,找出最小的元素
		{
			if(a[i]>a[j])     //交换类代码
			{
				temp = a[i];
				a[i]=a[j];
				a[j]=temp;				
			}
		}
	}
	
}           

2、参数传递

如果a是一个数组,很显然大家都知道如何传递参数,代码如下:

	int num =0 ;                       //在32机器中告诉C编译器分配4个字节的内存 
	int a [] = {1,3,5,12,6,7,54,32};   //告诉C编译器分配32个字节的内存 	
 //    num = sizeof(a)/sizeof(int);  
     num = sizeof(a)/sizeof(a[0]); 
	printf("排序之前:");
	printArray(a,num);
	sortArray(a,num); 
	printf("排序之后:");
	printArray(a,num);
}
如果a是一个单一整形变量的地址,还能类似于用 num = sizeof(a)/sizeof(a[0]) 求得num的值吗?如以下代码:

        int test =5;
	int *p = &test;
	int num1 = 0;
	
	num1 = sizeof(p)/sizeof(p[0]);
	sortArray(p,num1); 
	printf("排序之后:");
	printArray(p,num1);

           这样可以吗?很多人犯迷糊了,p[0]不是指数组首元素的值吗,这里p不是数组啊,p[0]都好像不存在,怎么能这样用?我们一定还记得,在C语言中可以用指针表示数组的每一个元素,本质上,对同一个对象有两种不同的符号表示,如定义:a[n]时等价于*(a+n),即寻址到内存的a,然后移动n个单元,再取出数组。故p[0]等价于*(p+0),该值的类型为int型。

   num1=sizeof(p)/sizeof(p[0]) 等价于 num1=sizeof(p)/sizeof(int );

该语句在语法上面没有任何错误,但是在32机器和64位机器运行结果不同,在32机器出现正常结果,64位机器出现错误结果,原因见本文最后。

3、声明数组参量

前提:实际参数是一个数组名。C对于int a  [ ] 和 int * a作了同样解释,即a是指向int的指针。 
由于原型允许省略名称,因此下列4种原型都是等价的。
/**   函数原型声明4中等价形式 
int sum (int *a , int n)
int sum (int * , int )
int sum (int a[] , int n)
int sum (int [] , int )   //可能略微不熟悉的一种 
*/ 
       定义函数时,名称是不可以省略的,以下两种形式是等价的。

/**   函数原型声明4中等价形式 
int sum (int *a , int n)
{}
int sum (int a[] , int n)
{}
*/ 

4、a与&a的区别

	int num =0 ;                       //在32机器中告诉C编译器分配4个字节的内存 
	int a [] = {1,3,5,12,6,7,54,32};   //告诉C编译器分配32个字节的内存 
	
	printf("a:%d ,a+1:%d,&a:%d,&a+1:%d\n",a,a+1,&a,&a+1) ;
	
	//a+1 和 &a+1 结果不一样  
	//虽然输出结果上面,a和&a一样 。 但是a 和 &a所代表的数据类型不一样
	
	/*重要*/ 
	//a 代表的数据首元素的地址 (首元素),同时与整个数组地址重合,但其不能代表整个数组,只能代表起始个体的地址 
	//&a代表的是整个数组的地址   (特别特别的注意) 它的加1是以整块数组所占字节数总数为单位1

输出结果:a:1638176 ,a+1:1638180,&a:1638176,&a+1:1638208

5、指针所占字节数

              指针所占用的字节数和操作系统和编译器有关。
/**
2016-7-12 Jason Gel 
**/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//void printArray(int * a ,int num ) 和  void printArray(int a[] ,int num )是等价的

//函数定义时候,名称是不可以省略的。函数原型容许省略名称。
/**   函数原型声明4中等价形式 
int sum (int *a , int n)
int sum (int * , int )
int sum (int a[] , int n)
int sum (int [] , int )   //可能略微不熟悉的一种 
*/ 
 
void printArray(int * a ,int num )
{
	int i ;
	for(i = 0; i< num; i++)
	{
		printf("%3d",a[i]);
	}
	printf("\n");
}
//这里用的是冒泡排序(起泡排序) 
void sortArray(int *a ,int num )
{
	int i ,j ,temp;
	for(i =0 ;i <num;i++)              //外层:每次选定出需要排序的一个元素,依次向后
	{
		for( j=i+1; j<num; j++ )  //内层:外层选定的一个元素与其后所有元素依次比较,找出最小的元素
		{
			if(a[i]>a[j])     //交换类代码
			{
				temp = a[i];
				a[i]=a[j];
				a[j]=temp;				
			}
		}
	}
	
}                         

int main ()
{
	int num =0 ;                       //在32机器中告诉C编译器分配4个字节的内存 
	int a [] = {1,3,5,12,6,7,54,32};   //告诉C编译器分配32个字节的内存 
	
	int test =5;
	int *p = &test;
	int num1 = 0;
	
	num1 = sizeof(p)/sizeof(p[0]);
	
	printf("num1:%d, sizeof(p):%d,sizeof(p[0]):%d \n",num1,sizeof(p),sizeof(p[0]));
	sortArray(p,num1); 
	printf("单一元素排序之后:");
	printArray(p,num1);
	
	printf("a:%d ,a+1:%d,&a:%d,&a+1:%d\n",a,a+1,&a,&a+1) ;
    printf("sizeof(num1):%d\n",sizeof(num1)); 
    printf("sizeof(a):%d\n\n",sizeof(a)); 
	printf("sizeof(int):%d sizeof(double):%d sizeof(char):%d \n",sizeof(int),sizeof(double),sizeof(char)) ;
	
	printf("sizeof(int *):%d sizeof(double*):%d sizeof(char*):%d \n",sizeof(int *),sizeof(double*),sizeof(char*)) ;
	
	//a+1 和 &a+1 结果不一样  
	//虽然输出结果上面,a和&a一样 。 但是a 和 &a所代表的数据类型不一样
	
	/*重要*/ 
	//a 代表的数据首元素的地址 (首元素),同时与整个数组地址重合,但其不能代表整个数组,只能代表起始个体的地址 
	//&a代表的是整个数组的地址   (特别特别的注意) 它的加1是以整块数组所占字节数总数为单位1
	
	
//	num =sizeof(a);//这个是获取的整个数组的字节数,为32个字节
	printf("实参a的数据类型为整个数组,所占字节为:%d \n",sizeof(a)) ;
//    num = sizeof(a)/sizeof(int);  
    num = sizeof(a)/sizeof(a[0]); //注意规范
	printf("排序之前:");
	printArray(a,num);
	sortArray(a,num); 
	printf("排序之后:");
	printArray(a,num);
	return 0;
}

VC 32位编译器 运行截图:

技术分享

64位编译器运行截图:

技术分享

核心:

可以看出在64位机器中,int*的指针为8个字节,在32位中int*为 4个字节,由于:

sizeof(p)/sizeof(p[0]) //等价于sizeof(int * ) /sizeof( int )

所以在64位机器上面原本应该为1的现在变成了2,导致程序出现错误。


      从程序输出结果我们可以看出:实参a的数据类型为整个数组,所占字节为32。虽然实参a表示的是数组名,但是它实际的数据类型不是int *,而是表示的整个数组所占字节数。这里不要与前文的a与&a表示地址时候弄混淆。

       


    

C语言中值得深入知识点----数组做函数参数、数组名a与&a区别、数组名a的"数据类型"

标签:

原文地址:http://blog.csdn.net/jin13277480598/article/details/51891816

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!