程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言入門知識 >> C語言中值得深入知識點

C語言中值得深入知識點

編輯:C語言入門知識

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 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
#include
#include

//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 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表示地址時候弄混淆。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved