C指向二维数组

Chr*_*bax 27 c arrays pointers

我知道有几个问题可以提供良好(和工作)的解决方案,但没有恕我直言,这清楚地说明了实现这一目标的最佳方法.所以,假设我们有一些2D数组:

int tab1[100][280];
Run Code Online (Sandbox Code Playgroud)

我们想要制作一个指向这个2D数组的指针.为实现这一目标,我们可以做到:

int (*pointer)[280]; // pointer creation
pointer = tab1; //assignation
pointer[5][12] = 517; // use
int myint = pointer[5][12]; // use
Run Code Online (Sandbox Code Playgroud)

或者,或者:

int (*pointer)[100][280]; // pointer creation
pointer = &tab1; //assignation
(*pointer)[5][12] = 517; // use
int myint = (*pointer)[5][12]; // use 
Run Code Online (Sandbox Code Playgroud)

好的,两者似乎都运作良好.现在我想知道:

  • 什么是最好的方式,第一或第二?
  • 两者都等于编译器?(速度,性能......)
  • 这些解决方案中的一个比其他解决方案占用更多内存?
  • 开发人员更常使用的是什么?

oli*_*bre 26

//defines an array of 280 pointers (1120 or 2240 bytes)
int  *pointer1 [280];

//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280];      //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
Run Code Online (Sandbox Code Playgroud)

使用pointer2pointer3生成相同的二进制文件,除了操作,++pointer2WhozCraig所指出的那样.

我建议使用typedef(产生与上面相同的二进制代码pointer3)

typedef int myType[100][280];
myType *pointer3;
Run Code Online (Sandbox Code Playgroud)

注意:从C++ 11开始,您也可以使用关键字using代替typedef

using myType = int[100][280];
myType *pointer3;
Run Code Online (Sandbox Code Playgroud)

在你的例子中:

myType *pointer;                // pointer creation
pointer = &tab1;                // assignation
(*pointer)[5][12] = 517;        // set (write)
int myint = (*pointer)[5][12];  // get (read)
Run Code Online (Sandbox Code Playgroud)

注意:如果tab1在函数体中使用数组=>此数组将放在调用堆栈内存中.但堆栈大小有限.使用大于空闲内存堆栈的数组会导致堆栈溢出崩溃.

完整的代码片段可在线编辑,网址gcc.godbolt.org

int main()
{
    //defines an array of 280 pointers (1120 or 2240 bytes)
    int  *pointer1 [280];
    static_assert( sizeof(pointer1) == 2240, "" );

    //defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
    int (*pointer2)[280];      //pointer to an array of 280 integers
    int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers  
    static_assert( sizeof(pointer2) == 8, "" );
    static_assert( sizeof(pointer3) == 8, "" );

    // Use 'typedef' (or 'using' if you use a modern C++ compiler)
    typedef int myType[100][280];
    //using myType = int[100][280];

    int tab1[100][280];

    myType *pointer;                // pointer creation
    pointer = &tab1;                // assignation
    (*pointer)[5][12] = 517;        // set (write)
    int myint = (*pointer)[5][12];  // get (read)

    return myint;
}
Run Code Online (Sandbox Code Playgroud)


Jey*_*ram 9

int *pointer[280]; //创建280个int类型的指针.

在32位操作系统中,每个指针有4个字节.所以4*280 = 1120字节.

int (*pointer)[100][280]; //仅创建一个指针,用于指向[100] [280]整数的数组.

这里只有4个字节.

来你的问题,int (*pointer)[280];并且int (*pointer)[100][280];是不同的,虽然它指向[100] [280]的相同2D阵列.

因为如果int (*pointer)[280];递增,那么它将指向下一个1D数组,但是在其中int (*pointer)[100][280];穿过整个2D数组并指向下一个字节.如果该内存不属于您的进程,则访问该字节可能会导致问题.


Fer*_*yer 9

你的例子都是等价的.然而,第一个不太明显,更"hacky",而第二个明确表明你的意图.

int (*pointer)[280];
pointer = tab1;
Run Code Online (Sandbox Code Playgroud)

pointer指向280个整数的1D数组.在你的任务,你实际上分配第一tab1.这是有效的,因为您可以隐式地将数组转换为指针(到第一个元素).

在使用时pointer[5][12],C将其pointer视为数组数组(pointer[5]属于类型int[280]),因此这里有另一个隐式转换(至少在语义上).

在第二个示例中,您显式创建了一个指向2D数组的指针:

int (*pointer)[100][280];
pointer = &tab1;
Run Code Online (Sandbox Code Playgroud)

这里的语义更清晰:*pointer是一个2D数组,所以你需要使用它来访问它(*pointer)[i][j].

两种解决方案都使用相同数量的内存(1个指针),并且很可能同样快速运行.在引擎盖下,两个指针甚至会指向相同的内存位置(tab1数组的第一个元素),并且您的编译器甚至可能生成相同的代码.

第一个解决方案是"更高级",因为人们需要非常深入地了解数组和指针如何在C中工作以了解正在发生的事情.第二个更明确.