创建有问题的二维阵列(C)

创建有问题的二维阵列(C),c,multidimensional-array,C,Multidimensional Array,下面的代码是我试图实例化2d数组,但它的实例化不正确: 守则: FILE* kernalFile = fopen(argv[1], "r"); int rKernalSize; fscanf(kernalFile, "%d", &rKernalSize); unsigned int rKernal[rKernalSize][rKernalSize]; 运行代码后立即从断点获取数据: rKernalSize值: Name : rKernalSize

下面的代码是我试图实例化2d数组,但它的实例化不正确: 守则:

    FILE* kernalFile = fopen(argv[1], "r");
    int rKernalSize;
    fscanf(kernalFile, "%d", &rKernalSize);
    unsigned int rKernal[rKernalSize][rKernalSize];
运行代码后立即从断点获取数据: rKernalSize值:

Name : rKernalSize
    Details:3
    Default:3
    Decimal:3
    Hex:0x3
    Binary:11
    Octal:03
rKernal值:

Name : rKernal
    Details:0x7ffffffe0cd0
    Default:[0]
    Decimal:[0]
    Hex:[0]
    Binary:[0]
    Octal:[0]

它应该是
rKernal[3][3]
,这是您可以查看的文件。如果需要:

3 -1 1 0 1 0 -1 0 -1 1 3 -1 1 0 1 0 -1 0 -1 1 3 -1 1 0 1 0 -1 0 -1 1

TLDR:
rKernalSize
是正确的(3),但是当我使用
rKernal[rKernalSize][rKernalSize]
创建2d数组时,它没有正确实例化!它设置为
rKernal[][0]
可能这是默认设置,但应该是
rKernal[3][3]
这里的基本问题是,在分配数组时,编译时不知道
rKernalSize
。在编译时,
int rKernalSize
的值依赖于编译器(除非新的C标准明确将其设置为0;无论如何,0是我打赌的值)。因此,当加载代码时,有一个符号
rKernal
表示不包含字节的内存分区的地址

然后你运行程序,用你的scanf读“3”;当您转储结果时,会看到“3”

顺便说一下,这段代码不能在纯C语言中工作——您必须在第一条可执行语句之前进行分配。这将在C++中编译。 现在,如果你想用C来做这样的事情,下面是你需要的:

  • 使用scanf读取您的尺码

  • 使用
    malloc
    为阵列分配内存,如下所示

x

  • 现在,由于C中的指针数组二元性,可以将其视为数组 x

    ari[1][1]=42;//答案是


    • 忘记调试器告诉您的内容。在您的代码中,紧接着:

      unsigned int rKernal[rKernalSize][rKernalSize];
      
      声明如下:

      printf ("%d\n", sizeof(rKernal) / sizeof(unsigned int));
      
      并查看它打印出的内容(希望
      9

      在编译时创建的调试信息可能不足以正确确定可变长度数组的大小


      举例来说,尽管
      gcc
      支持可变长度数组,
      gdb
      本身直到2009年底都无法正确处理它们,而且2010年10月的文档中仍然没有提到它们


      所以我怀疑这就是问题所在,特别是因为我在上面提供的测试代码按照预期输出了
      9

      什么是“它没有正确实例化”的意思?你说“没有正确实例化!”是什么意思?编译时没有对
      sizeof
      进行评估吗?(ed:我猜对于C99中的动态大小数组,它是…)如果我这样做,我会得到以下警告:警告:格式“%d”要求类型为“int”,但参数2的类型为“long unsigned”int@Mark:No.C99 6.5.3.4/2状态
      如果操作数的类型是可变长度数组类型,则对操作数求值;否则,操作数不会被计算,结果是一个整数常量。
      @Jacob:当您运行它时,会发生什么?接下来就是了(忽略警告,这一行是用于调试的临时行:您可以使用正确格式的字符串修复它,但不必使用YAGNI)。底线:您的数组创建正确。事实上,调试器没有足够的信息来计算它在运行时有多大,这是调试器的一个缺陷。确切地说,您必须使用“malloc”并动态分配内存@迈克尔:事实上,你没有。C99引入了可变长度数组的概念,因此该代码在该标准的迭代下是有效的。链接页面中隐藏着代码片段最后,在C99中,您可以使用可变长度数组。:-)GCC做得很好。这些标准从1999年开始就存在了,我想是的,如果你的供应商不支持它,你应该考虑移动:-),而且问题不是关于编译时错误的事实意味着提问者的编译器也支持C99。我不相信你可以将
      ari
      索引为
      ari[1][1] 
      如您所述;当您仅分配一块内存时,编译器没有足够的信息将其转换为适当的偏移量。相反,索引需要采用
      ari[1*rkSize+1]的形式
      @paxdiablo:没错。我想我几乎所有的C代码都是按照C90标准编写的。无论如何,谢谢!
      unsigned int rKernal[rKernalSize][rKernalSize];
      
      printf ("%d\n", sizeof(rKernal) / sizeof(unsigned int));