从 C 中现有的一维数组创建二维数组?

Wak*_*nka 5 c arrays

在 perl 中,我可以创建一维数组,然后从它们创建二维数组,如下所示:

@a1=(a,b,c)
@a2=(d,e,f)
@a3=(g,h,i)
@m23_v1=(\@a1,\@a2,\@a3)
Run Code Online (Sandbox Code Playgroud)

这是另一种方式(假设@a1@a2@a3与前面的示例相同):

@m23_v2=([@a1],[@a2],[@a3])
Run Code Online (Sandbox Code Playgroud)

这两种方式之间的区别在于,当使用反斜杠时,更改$a[0][0]也会更改$a1[0]。另一方面,当使用括号时,值将被复制,因此更改$a[0][0]不会更改$a1[0]。波纹管是变量的内存地址,它们应该阐明我的意思:

print \$a1[0]
SCALAR(0x2006c0a0)

print \$m23_v1[0][0]
SCALAR(0x2006c0a0)

print \$m23_v2[0][0]
SCALAR(0x2030a7e8)
Run Code Online (Sandbox Code Playgroud)

如何在 C 中实现相同的功能?我试过以下代码:

# include <stdio.h>
int main(){
  int a1[3] = {1,2,3};
  int a2[3] = {4,5,6};
  int m23[2][3] = {a1, a2};
  printf("%d\n", a1[0]);
  printf("%d\n", m23[0][0]);
}
Run Code Online (Sandbox Code Playgroud)

但它给了我以下编译警告:

2d.c: In function ‘main’:
2d.c:4:3: warning: initialization makes integer from pointer without a cast [enabled by default]
2d.c:4:3: warning: (near initialization for ‘m23[0][0]’) [enabled by default]
2d.c:4:3: warning: initialization makes integer from pointer without a cast [enabled by default]
2d.c:4:3: warning: (near initialization for ‘m23[0][1]’) [enabled by default]
2d.c:5:3: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
Run Code Online (Sandbox Code Playgroud)

执行后,C 代码返回以下内容:

1
-1077371888
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 为什么我会收到编译警告以及如何修改代码以摆脱它们?
  2. 如果给定的 C 相当于反斜杠的 perl 版本,那么括号版本的等价物是什么(反之亦然)?
  3. 为什么我得到 -1077371888 而不是 1?

Grz*_*ski 3

您可以使用指针数组来获得等效的反斜线版本(即@m23_v1):

#include <stdio.h>

int main(void)
{
    int a1[3] = {1,2,3};
    int a2[3] = {4,5,6};

    int *m23[2] = {a1, a2};

    printf("%d\n", a1[0]);
    printf("%d\n", m23[0][0]);

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

在你的代码中:

int m23[2][3] = {a1, a2};
Run Code Online (Sandbox Code Playgroud)

初始化器期望用整数填充。基本上你用两个整数创建二维数组:a1a2。其余元素用零初始化。为了说明这一点,这看起来像:

int m23[2][3] = {0xaaee33, 0xaaee55, 0, 0, 0, 0};
Run Code Online (Sandbox Code Playgroud)

这实际上等同于:

int m23[2][3] = {{0xaaee33, 0xaaee55, 0}, {0, 0, 0}}; // two rows, three columns
Run Code Online (Sandbox Code Playgroud)

但是,a1不是整数。它是数组的名称,隐式转换为int(转换为指针后,指向数组的第一个元素)。换句话说,您正在隐式转换a1和的地址a2的地址隐式转换为两个整数。事实上,这样的操作在 C 中是非法的,这样的代码甚至不应该使用-pedantic-errors标志(或等效的)进行编译。

括号版本的等效项是什么(反之亦然)?

花括号版本的等效项是定义一个特定大小的多维数组,然后将a1a2数组的每个元素复制到其中:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int a1[3] = {1,2,3};
    int a2[3] = {4,5,6};

    int m23[2][3];
    memcpy(m23 + 0, a1, sizeof(a1));
    memcpy(m23 + 1, a2, sizeof(a2));

    printf("%d\n", a1[0]);
    printf("%d\n", m23[0][0]);

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