歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C語言中的二級指針和二維數組問題

關於二級指針和二維數組兩者差別很大,不可以直接用二級指針傳遞二維數組

首先來看看二維數組在內存中是如何組織的呢?

一維數組 T arr1 = new T[9]  二維數組T arr2 = new T[3][3]

實際上,不管是一維還是多維數組,都是內存中一塊線性連續空間,因此在內存級別上,其實都只是一維。但是不同的定義使得表現形式不一樣,從而有多維數組的概念。訪問數組元素其實非常簡單,原因就在於元素在內存中的線性排列,這樣對一維數組的訪問只需要arr1[index] = *(arr1+index*sizeof(T));對二維數組的訪問

arr2[i][j]=*(arr2+(i*col+j)*sizeof(T)),因此連續線性的數組訪問效率很高。多維類似。

下面一個程序測試:

#include<cstdio>

/************************************************************************/
/* 數組和指針參數是如何被編譯器修改的?

  “數組名被改寫成一個指針參數”規則並不是遞歸定義的。數組的數組會被改寫成“數組的指針”,而不是“指針的指針”:
 
  實參                                                所匹配的形參
 
數組的數組            char c[8][10];                char (*c)[10];        數組指針
 
指針數組              char *c[10];                  char **c;              指針的指針
 
數組指針(行指針)      char (*c)[10];                char (*c)[10];        不改變
   
指針的指針            char **c;                      char **c;              不改變                                                                    */
/************************************************************************/
/*二級指針**作為形參,可以接受二級指針**p、指針數組*p[]作為實參的參數,從而傳遞二維數組*/
void print(int **p, int row, int col)
{
 int i=0,j=0;
 for(i=0;i<row;i++)
 {
  for(j=0;j<col;j++)
  {
   printf("%d\t",p[i][j]);
  }
 }
 printf("\n");
}
/*數組指針(*)[]作為形參,可以接受數組指針(*p)[3]作為實參的參數,從而傳遞二維數組*/
void print(int (*p)[3], int row, int col)
{
 int i=0,j=0;
 for(i=0;i<row;i++)
 {
  for(j=0;j<3;j++)
  {
   printf("%d\t",p[i][j]);
  }
 }
 printf("\n");
}

/*function 'void __cdecl print(int ** ,int,int)' already has a body Error executing cl.exe.
/*同二級指針*/
/*
void print(int *p[], int row, int col)
{
 int i=0,j=0;
 for(i=0;i<row;i++)
 {
  for(j=0;j<col;j++)
  {
   printf("%d\t",p[i][j]);
  }
 }
 printf("\n");
}
*/
/******以上兩個函數無法重載overload,說明編譯器把*p[]和**p  都當成一種類型******************************************/


int main()
{

 int i = 0;
 int **pointer_to_pointer;
 //printf("%X\n",*pointer_to_pointer);//會錯誤,因為pointer_to_pointer 還未初始化,是野二級指針
 
 int *pointer = new int[9];
 
 int *pointer_array[3]; //指針數組,即是一個存放指針元素的數組,定義後即會有含有三個指針元素的數組,但是每個指針元素並沒有初始化
 printf("%X\t%X\t%X\n",pointer_array,pointer_array+1,pointer_array+2);
 printf("%X\t%X\t%X\n",pointer_array[0],pointer_array[1],pointer_array[2]);

 
 int bi_array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
 int (*array_pointer)[3] = bi_array;//數組指針,指向數組的指針,可用於函數傳遞二維數組
 int single_array[3] = {1,2,3};

   //pointer_to_pointer = bi_array;  //!!! 錯誤,二級指針和二維數組首地址(實際內存空間不管是N維數組,都是一片連續的線性空間,二維數組元素訪問a[i][j]是a+sizeof(type)*(C*i+j),因此a可以看成是一個指針而已)不是一個東西,二者不能相互賦值
          //cannot convert from 'int [3][3]' to 'int ** '

 //pointer_to_pointer = (int**)bi_array; // !!!慎用,因為雖然沒有語法錯誤,但是會出現內存訪問錯誤;

    //pointer_array = bi_array;//錯誤cannot convert from 'int [3][3]' to 'int *[3]'
 

 
 //pointer_to_pointer = bi_array+1;//錯誤cannot convert from 'int (*)[3]' to 'int ** '
 /*******************以上說明二維數組和二維指針不是等價的,不能相互賦值*************************************************/
 
 pointer_to_pointer = pointer_array;
 /*******以上這句說明指針數組*[]  可以轉換為二級指針** 他們相互等價*****************************************************/
 

 //pointer = bi_array;//錯誤cannot convert from 'int [3][3]' to 'int *'
 pointer = (int *)bi_array;
 for(i=0;i<9;i++)
 {
  printf("%d\t",pointer[i]);
 }
 printf("\n");

 
 
 //pointer = array_pointer;//錯誤cannot convert from 'int (*)[3]' to 'int *'
 pointer = (int *)array_pointer;
 for(i=0;i<9;i++)
 {
  printf("%d\t",pointer[i]);
 }
 printf("\n");

 for(i=0;i<9;i++){pointer[i] = 9;}    //此時指向bi_array的array_pointer的元素被pointer修改為9
 array_pointer = (int(*)[3])pointer;
 print(array_pointer,3,3);
 /********以上說明二維數組名和數組指針雖然是一個指針,但編譯器並不理解,對他來說是數組類型的指針,但可以類型強制轉換*****/
 

 for(i=0;i<3;i++)
 {
  pointer_array[i] = bi_array[i];
 }
 printf("\n");

 print((int(*)[3])pointer,3,3);
 print(pointer_to_pointer, 3 ,3);
 print(pointer_array, 3, 3);
 return 0;
}

對二維數組做如下總結:

1.二維數組和二維指針不是等價的,不能相互賦值

2.指針數組*[] 可以轉換為二級指針** 他們相互等價

3.二維數組名和數組指針雖然是一個指針,但編譯器並不理解,對他來說是數組類型的指針,但可以類型強制轉換

pointer = (int *)array_pointer;    array_pointer = (int(*)[3])pointer;  pointer = (int *)bi_array;

4.如果想用函數傳遞二維數組,一般形參用二級指針**p或指針數組*[],可以支持二級指針和指針數組的實參傳遞,特殊的還可以用(*p)[N]

------------------------------分割線------------------------------

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved