簡體   English   中英

在C / C ++中,char * arrayName [] []是指向指針的指針還是指向指針的指針?

[英]In C/C++, is char* arrayName[][] a pointer to a pointer to a pointer OR a pointer to a pointer?

我理解多維數組作為指針的指針,但也許我錯了?

例如,我雖然:

char * var = char var[]

char ** var = char* var[]char var[][]

char *** var = char var[][][]char* var[][]char** var[]

這是不正確的? 我很困惑,因為我在簡單的教科書示例中看到了char * [] []演員作為char **。

我粘貼了下面的例子。 任何人都可以為我清除這個嗎? 謝謝!


/* A simple dictionary. */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* list of words and meanings */

char  *dic[][40] = {
    "atlas", "A volume of maps.",
    "car", "A motorized vehicle.",
    "telephone", "A communication device.",
    "airplane", "A flying machine.",
    "", ""  /* null terminate the list */
};

int main(void)
{
    char word[80], ch;
    char **p;

do {
    puts("\nEnter word: ");
    scanf("%s", word);
    p = (char **)dic;
    /* find matching word and print its meaning */
    do {
        if(!strcmp(*p, word)) {
            puts("Meaning:");
            puts(*(p+1));
            break;
            }

        if(!strcmp(*p, word)) break;

        p = p + 2;  /* advance through the list */
        } while(*p);

    if(!*p) puts("Word not in dictionary.");
    printf("Another? (y/n): ");
    scanf(" %c%*c", &ch);

    } while(toupper(ch) != 'N');

return 0;

}

C的規則如下:

6.3.2.1左值,數組和函數指示符
...
3除非它是sizeof運算符或一元運算符的操作數,或者是用於初始化數組的字符串文字,否則將類型為''array of type''的表達式轉換為類型為''指針的表達式鍵入''指向數組對象的初始元素,而不是左值。 如果數組對象具有寄存器存儲類,則行為未定義。

C ++的語言有點不同:

4.2數組到指針的轉換[conv.array]

1“NT的數組”或“T的未知邊界數組”類型的左值或右值可以轉換為“指向T的指針”的右值。 結果是指向數組的第一個元素的指針。
...
8.3.4數組[dcl.array]
...
7多維數組遵循一致的規則。 × × ... × , then E appearing in an expression is converted to a pointer to an ( −1)-dimensional array with rank × ... × . 如果E是秩 × ×...× 的n維數組,那么出現在表達式中的E被轉換為指向具有等級 ×...× 的( -1)維數組的指針。 −1)-dimensional array, which itself is immediately converted into a pointer. 如果將*運算符(由於下標而顯式或隱式)應用於此指針,則結果是指向的( -1)維數組,該數組本身立即轉換為指針。

所以以下都適用:

Declaration        Expression        Type             Decays to
-----------        ----------        ----             ---------
     T a[N]                 a        T [N]            T *
                           &a        T (*)[N]     
                           *a        T
                         a[i]        T

  T a[M][N]                 a        T [M][N]         T (*)[N]
                           &a        T (*)[M][N]  
                           *a        T [N]            T *
                         a[i]        T [N]            T *
                        &a[i]        T (*)[N]      
                        *a[i]        T
                      a[i][j]        T

T a[M][N][O]                a        T [M][N][O]      T (*)[M][N]
                           &a        T (*)[M][N][O]
                           *a        T [M][N]         T (*)[N]
                         a[i]        T [M][N]         T (*)[N]
                        &a[i]        T (*)[M][N]  
                        *a[i]        T [N]            T *
                      a[i][j]        T [N]            T *
                     &a[i][j]        T (*)[N]
                     *a[i][j]        T
                   a[i][j][k]        T

對於更高維的陣列,該模式應該是清晰的。

那么讓我們分析你的字典:

/* list of words and meanings */         

char  *dic[][40] = {         
    "atlas", "A volume of maps.",         
    "car", "A motorized vehicle.",         
    "telephone", "A communication device.",         
    "airplane", "A flying machine.",         
    "", ""  /* null terminate the list */         
};

這不會按照你想要的方式設置你的字典; 你基本上把它設置為一個包含40個指向char的1元素數組。 如果你想要一組字符串對,那么聲明應如下所示:

char *dic[][2] = 
{
  {"atlas", "A volume of maps"},
  {"car", "A motorized vehicle"},
  {"telephone", "A communication device"},
  {"airplane" , "A flying machine"},
  {NULL, NULL} // empty strings and NULLs are different things.  
}; 

dic的類型是“指向char的2元素數組的5元素數組”或char *[5][2] 按照上面的規則,表達式dic應該衰減為char *(*)[2] - 指向char *(*)[2]的指針的2元素數組的指針。

搜索此字典的函數將如下所示:

char *definition(char *term, char *(*dictionary)[2]) // *NOT* char ***dictionary
{
  while ((*dictionary)[0] != NULL && strcmp((*dictionary)[0], term) != 0)
    dictionary++;
  return (*dictionary)[1];
}

你會從你的主要功能中調用它

char *def = definition(term, dic);

請注意,我們必須在函數中的*dictionary表達式周圍使用括號。 數組下標operator []優先級高於dereference運算符* ,我們不想直接下標到dictionary ,我們想要下標到dictionary 指向的數組中。

我理解多維數組作為指針的指針,但也許我錯了?

是的,你錯了。 數組和指針之間存在差異。 數組可以衰減成指針,但指針不會攜帶有關它所指向的數組的大小或配置的狀態。 不要將這種自動衰減與數組和指針相同的想法混淆 - 它們不是。

char **是指向包含字符指針的內存塊的指針,字符指針本身指向字符的內存塊。 char [][]是包含字符的單個內存塊。

如果你有一個char **並使用ptr[x][y]訪問它,編譯器會將其更改為*(*(ptr + x)+y) 如果你有char [][] ,編譯器會將arr[x][y]更改為*(ptr + rowLength*y + x) 注意 :我在Xs和Ys的順序上沒有110%的正面,但這對於我在這里提出的點並不重要)注意,給定指針,編譯器不知道任何關於大小的信息或者數組的維度,如果將指針視為多維數組,則無法確定實際地址。

char *dic[][40]一個大小char *dic[][40] 的數組數組,包含字符指針 因此它根本不符合您的作業。

p = (char **)dic; < - 這就是演員陣容不好的原因。 編譯器告訴你,你真正想對dic做的事沒有任何意義。 但是因為您可以將指針強制轉換為任何其他指針,所以即使嘗試以這種方式讀取數據也會導致未定義的行為,轉換也會成功。

你需要參考'右邊的規則' 或者你可以在這里消除大部分C-ish聲明

所以,

char *p[2][3]被解析為

p是一個包含2個元素的數組,其中每個元素是一個包含3個元素的數組,這樣每個元素都是一個指向一個字符的指針。([]綁定強於*)

char (*p)[2][3]被解析為

“p是指向2個元素char數組的指針,其中每個元素都是3個元素的char數組。” (括號綁定最強)

沒有看太多細節,但我認為作者依賴於c布局一個像這樣的2d字符串數組:

連續內存中的鍵,值,鍵,值,鍵,值。 然后遍歷這個數組作為1d數組的字符串p = (char **)dic;

這是C的美女和潛在問題之一 - 它具有很多低級別的功能,但是你可以通過合適的代碼保護自己以防止副作用。

我和*[]組合的記憶規則之一是main的簽名。 作品! :-)

你的dic是一個40元素數組的數組,每個元素都是一個指向char的指針。

#include <iostream>
#include <typeinfo>
using namespace std;

template< class Type, unsigned N >
void tellMeAbout( Type const (&)[N] )
{
    cout << "Well, it's an array of " << typeid( Type ).name() << ".\n";
}

int main()
{
    char  *dic[][40]    = { 0 };
    tellMeAbout( dic );
}

使用Visual C ++我得到...

好吧,這是一個char * [40]的數組。

干杯&hth。,

- 阿爾夫

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM