C语言中的多维数组访问

C语言中的多维数组访问,c,arrays,memory,system,C,Arrays,Memory,System,我知道多维数组是连续分配的,所以int[4][3]arr;将在一行中分配12个整数单元格 我的第一个问题是,鉴于C不跟踪数组的长度,它如何知道将双坐标访问模式转换为单坐标内存地址所需的正确算法?例如,如果 arr == 0x? // some memory address 然后 这三辆车是从哪里来的 我的第二个问题是,当在堆上分配数组时,它们是否仍然以相同的连续方式分配?或者它是作为一个指针数组来实现的,它取消了对一维数组的引用 编译器只记住类型,包括 数组变量。这样,当您访问它时,它知道要做

我知道多维数组是连续分配的,所以int[4][3]arr;将在一行中分配12个整数单元格

我的第一个问题是,鉴于C不跟踪数组的长度,它如何知道将双坐标访问模式转换为单坐标内存地址所需的正确算法?例如,如果

arr == 0x? // some memory address
然后

这三辆车是从哪里来的

我的第二个问题是,当在堆上分配数组时,它们是否仍然以相同的连续方式分配?或者它是作为一个指针数组来实现的,它取消了对一维数组的引用

编译器只记住类型,包括 数组变量。这样,当您访问它时,它知道要做什么

编译器将在堆或堆栈上以相同的方式处理数组。指针数组是完全不同的类型,因此它没有其他选择

请注意,使用当前的高级编译器优化,不可能知道最终代码实际将执行什么操作,这取决于您如何使用数组。例如,如果只访问一列,其他列可能会被优化掉,从而在内存中形成一个一维数组

编译器只记住类型,包括 数组变量。这样,当您访问它时,它知道要做什么

编译器将在堆或堆栈上以相同的方式处理数组。指针数组是完全不同的类型,因此它没有其他选择


请注意,使用当前的高级编译器优化,不可能知道最终代码实际将执行什么操作,这取决于您如何使用数组。例如,如果只访问了一列,其他列可能会被优化掉,从而在内存中形成一个一维数组。

C确实跟踪数组长度,但仅在编译时跟踪,而不是在运行时跟踪。它不会保存在数组结构中:

#include <stdio.h>

int main(int argc, char **argv)
{
  char array[] = "hello world";
  char* char_ptr = array;

  printf("array size: %lu\n", sizeof(array));
  printf("char_ptr size: %lu\n", sizeof(char_ptr));
  printf("void_ptr size: %lu\n", sizeof(void*));

  int matrix[2][3] = {{1,2,3},{4,5,6}};
  printf("matrix size (items): %lu\n", sizeof(matrix)/sizeof(int));
  return EXIT_SUCCESS;
}

C中有一个细微差别,数组自动转换为指针,但指针和编译时声明的数组对于编译器来说仍然是两种不同的类型。

C确实跟踪数组长度,但仅在编译时跟踪,而不是在运行时跟踪。它不保存在数组结构中:

#include <stdio.h>

int main(int argc, char **argv)
{
  char array[] = "hello world";
  char* char_ptr = array;

  printf("array size: %lu\n", sizeof(array));
  printf("char_ptr size: %lu\n", sizeof(char_ptr));
  printf("void_ptr size: %lu\n", sizeof(void*));

  int matrix[2][3] = {{1,2,3},{4,5,6}};
  printf("matrix size (items): %lu\n", sizeof(matrix)/sizeof(int));
  return EXIT_SUCCESS;
}

在C语言中,数组会自动转换为指针,但指针和在编译时声明的数组对于编译器来说仍然是两种不同的类型。

它会跟踪长度。我们可以结束这个问题吗?它们实际上只是数组的数组,由于数组的大小是固定的,并且必须事先声明,编译器可以做适当的数学运算来取消对数组中任何项的引用。你把数组和指针混淆了。指针没有它们所指向的长度,但是数组是用它们的所有维度声明的。3是从哪里提取的?从2D数组int[4][3]arr[sic]的第二个指定维度开始。这是至关重要的,但第一维度不是,也许这就是你所困惑的。您可以声明一个函数fooint bar[][3],它确实需要知道第一个维度才能工作,但当然它需要以某种方式知道限制。它确实跟踪长度。我们可以结束这个问题吗?它们实际上只是数组的数组,由于数组的大小是固定的,并且必须事先声明,编译器可以做适当的数学运算来取消对数组中任何项的引用。你把数组和指针混淆了。指针没有它们所指向的长度,但是数组是用它们的所有维度声明的。3是从哪里提取的?从2D数组int[4][3]arr[sic]的第二个指定维度开始。这是至关重要的,但第一维度不是,也许这就是你所困惑的。您可以声明一个函数fooint bar[][3],它确实需要知道第一个维度才能工作,但当然它需要以某种方式知道限制。数组维度在运行时也是已知的。编译器可能使用存储,也可能不使用存储。对于编译时已知大小的数组,编译器可以将其烘焙到生成的代码中,因此通常不需要将数组维度存储在它们自己的任何位置。对于其他阵列,它可能需要,例如char ch[atoifoo];稍后使用sizeof ch。在运行时也知道数组维度。编译器可能使用存储,也可能不使用存储。对于编译时已知大小的数组,编译器可以将其烘焙到生成的代码中,因此通常不需要将数组维度存储在它们自己的任何位置。对于其他阵列,它可能需要,例如char ch[atoifoo];稍后使用sizeof ch。你的最后一句话是什么意思?@mattmcnab现在清楚了吗?是的,但实际上,只要程序输出相同,程序中的任何内容都可以优化为其他内容,因此这不是一个特殊的问题case@MattMcNabb因为这些问题都是基本的,我想最好再加上这个,确实是一般的,注意。你最后一句话是什么意思?@MattMcNabb现在明白了吗?是的,尽管事实上什么都没有
在你的程序中,任何东西都可能被优化,只要程序输出是相同的,所以这不是一个特殊的问题case@MattMcNabb因为这些问题都是基本的,我想最好也加上这句话,实际上是泛泛的。
array size: 12
char_ptr size: 8
void_ptr size: 8
matrix size (items): 6