繁体   English   中英

将二维数组指针传递给C中的函数

[英]passing 2D array pointer to function in C

我正在尝试将二维数组的地址传递给 C 中的函数。我将二维数组初始化为:

const int N = 3;
char t[N][N];

我尝试将其转换为字符***:

char*** t_ptr = &t;

但它失败了:

warning: initialization from incompatible pointer type

我想接收数组的函数有一个原型,例如:

void f(char*** t, int N) { ... };

我究竟做错了什么? 谢谢你。

这个

char*** t_ptr = &t;

编译器指出是错误的,因为t是一个二维数组,而不是像char***这样的三重指针,而是使用指向数组的指针来指向它。 例如

char t[3][3] = { "ab","de","gh"}; /* total 3 1D array & each 1D array has 3 elements */
char (*t_ptr)[3] = t; /* t_ptr is a pointer to an array, pointing to 3 elements at a time */

你可以像打印t_ptr一样

for(int index = 0; index < 3 ; index++) {
        printf("%s\n",t_ptr[index]);
}

阅读c声明,可以访问: https : //cdecl.org/

现在使用@Achal 的示例数组:


#include <stdio.h>
#include <stdlib.h>

int main()
{
    // t is a 2D array (not a VLA)

    char t[3][3] =
    {
        {'a', 'b', '\0'},
        {'d', 'e', '\0'},
        {'g', 'h', '\0'}
    };
    printf("t is composed of 3 arrays of 3 characters each,\n");
    printf("with the following addresses (on my machine):\n");
    printf("--------------------------------------------------\n");
    printf("%p, %p, %p\n", t[0], t[1], t[2]);


// ------------------------------------------------
    // p is an array of 3 char pointers or char*
    // Notice initialization
    char* p[3] = {t[0], t[1], t[2]};
    // following line of code will break, if no '\0' is encountered
    // since %s requires a char* and a null terminator

    printf("\nPrint strings using p:\n");
    printf("------------------------\n");
    printf("%s, %s, %s\n", *p, *(p + 1), *(p + 2));

// ------------------------------------------------
    // q is a pointer to a char* or q has type char**
    // Notice initialization of q (q points to p)

    char** q = p;
    printf("\nUsing q:\n");
    printf("-----------\n");
    printf("%s, %s, %s\n", *q, *(q + 1), *(q + 2));

// ---------------- printing characters individually
    printf("\nIndividually:\n");
    printf("---------------\n");
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            printf("%c ",
                  *(*(q + i) + j)
                   );
        }
        printf("\n");
    }
// -----------------------------------------------
    // r is a pointer to an array of size 3 containing char
    // r advances three char at a time (r doesn't know the size of t)

    char (*r)[3] = t;   // this is the type of t
    printf("\nUsing r:\n");
    printf("---------------\n");
    printf("%p, %p, %p\n", *r, *(r + 1), *(r + 2));

    // to extract chars
    printf("%c, %c", *(*(r + 0) + 0), *(*(r + 2) + 1));
// -----------------------------------------------

    return EXIT_SUCCESS;
}

输出:

t is composed of 3 arrays of 3 characters each,
with the following addresses (on my machine):
--------------------------------------------------
000000000022FE2F, 000000000022FE32, 000000000022FE35

Print strings using p:
------------------------
ab, de, gh

Using q:
-----------
ab, de, gh

Individually:
---------------
a b
d e

Using r:
---------------
000000000022FE2F, 000000000022FE32, 000000000022FE35
a, h
Process returned 0 (0x0)   execution time : -0.000 s
Press any key to continue.
char t[N][N];

实际上是一样的

char t[N * N];

在记忆中。 在这两种情况下,指向此类数组的指针都是char *类型。

char ***是指向指针的指针,即指向 char 的指针,而char *是指向char *的指针,这就是您在 C 中传递数组引用的方式:您将它们作为指向第一个元素的指针传递数组,第一个元素是一个字符。

一旦将数组传递给函数,C 就无法保留数组的确切类型或结构。 在内存中,字符数组只是一堆充满字符的内存,您可以传递的只是指向该内存的指针。 如果该内存是char []char [][]甚至char [][][]不起作用,则在内存中所有这三个都是一个充满字符的块,该函数必须明确知道内存中的结构,否则对于函数,所有 char 数组将始终为char []

我强烈不鼓励 C 初学者使用多维数组。 代替

char t[N][N];
char c = t[y1][x1];
t[y2][x2] = 'X';

char t[N];
char c = t[y1 * N + x1];
t[y2 * N + x2] = 'X';

因为这基本上是编译器在内部会做的事情。

注意C中的多维数组不是xy,而是yx,第一个值是行,第二个是列, 请看这个教程

谁不相信我刚才说的话,试试这个代码:

int main ( ) {
    char a[5][5];
    for (int y = 0; y < 5; y++) {
        for (int x = 0; x < 5; x++) {
            a[y][x] = x + 10 * y;
        }
    }

    for (int y = 0; y < 5; y++) {
        for (int x = 0; x < 5; x++) {
            printf("%02d ", a[y][x]);
        }
        printf("\n");
    }

    printf("------\n");

    char * a2 = (char *)a;
    for (int y = 0; y < 5; y++) {
        for (int x = 0; x < 5; x++) {
            printf("%02d ", a2[y * 5 + x]);
        }
        printf("\n");
    }
}

您可以在线运行它,如果您愿意,输出是相同的。 还可以查看编译器为任一循环(例如gcc -S )生成的汇编代码,您会发现它几乎相同,因为即使在第一种情况下,编译器也使用addmul指令访问正确的内存位置大批。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM