【问题标题】:c : multidimensional array using 1d array under the coversc : 使用 1d 数组的多维数组
【发布时间】:2012-03-03 09:31:55
【问题描述】:

我正在尝试 malloc 一个巨大的 4d 数组(192 gig 可用);但是输入的内容与输出的内容不匹配(请参见下面代码中的 assert() )。 (我把定义的尺寸变小了;但实际数字是:20,9000,195,120)

#define SIZE_A 1
#define SIZE_B 3
#define SIZE_C 4
#define SIZE_D 2

#define offSet(a,b,c,d) ( ((size_t) SIZE_A * SIZE_B * SIZE_C * a) + ((size_t) SIZE_B * SIZE_C * b) + ((size_t) SIZE_C * c) + d)

void xall(void)
{
int *aray = (int *) malloc( (size_t) SIZE_A * SIZE_B * SIZE_C *  SIZE_D  * sizeof(int));


int counter = 0;

    for (int a = 0; a < SIZE_A; ++a){
        for (int b = 0; b < SIZE_B; ++b){
            for (int c = 0; c < SIZE_C; ++c) {
                for (int d = 0; d < SIZE_D; ++d){
                    aray[ offSet(a,b,c,d) ] = counter++;

                }}}}


counter = 0;    
    for (int a = 0; a < SIZE_A; ++a){
        for (int b = 0; b < SIZE_B; ++b){
            for (int c = 0; c < SIZE_C; ++c) {
                for (int d = 0; d < SIZE_D; ++d){       
                    int value = aray[ offSet(a,b,c,d) ] ;
                    assert(value == counter++);

                }}}}
}

【问题讨论】:

    标签: c dynamic macros multidimensional-array


    【解决方案1】:

    正如其他人所提到的,您的宏是错误的。解决这个问题很好,但我建议您直接分配一个多维数组,而不是手动滚动偏移宏。看看这个例子:

    #include <assert.h>
    #include <stdlib.h>
    
    #define SIZE_A 1
    #define SIZE_B 3
    #define SIZE_C 4
    #define SIZE_D 2
    
    int main(void)
    {
      int counter = 0;
      int (*array)[SIZE_A][SIZE_B][SIZE_C][SIZE_D] = 
              malloc(sizeof(int) * SIZE_A * SIZE_B * SIZE_C *  SIZE_D);
    
      for (int a = 0; a < SIZE_A; ++a)
        for (int b = 0; b < SIZE_B; ++b)
          for (int c = 0; c < SIZE_C; ++c) 
            for (int d = 0; d < SIZE_D; ++d)
              (*array)[a][b][c][d] = counter++;
    
      counter = 0;    
      for (int a = 0; a < SIZE_A; ++a)
        for (int b = 0; b < SIZE_B; ++b)
          for (int c = 0; c < SIZE_C; ++c)
            for (int d = 0; d < SIZE_D; ++d)
            {
              int value = (*array)[a][b][c][d];
              assert(value == counter++);
            }
    
      return 0;
    }
    

    本例中分配的数组的内存布局与您的问题完全相同,但为什么不让编译器为您完成工作呢?

    暂且不说——不要在 C 程序中强制转换 malloc() 调用的返回值。从void * 的转换是隐式的,使用显式转换可以隐藏隐式函数声明警告,否则您会得到 - 例如,如果您忘记包含stdlib.h

    【讨论】:

    • 好点,但问题是 Visual c 的维度太大:数组的总大小超过 4 GB,我收到关于数组大小太大的 C2148 错误。
    • 但是您可以分配那么多并将其分配给一个简单的指针吗?我不明白。
    • 如果您的阵列大于 4 GB,您应该将更多内存放入您的 comp 并使用 64 位操作系统。
    • C2148 错误表示 array 的总大小不得超过 2^31-1 字节。但是您仍然可以malloc 更多。所以这只是一个编译器限制。
    • @mikithskegg:我使用的是 64 位操作系统,我的工作站最大容量为 192 gig(没错,是千兆字节,而不是兆字节)。还有其他建议吗?
    【解决方案2】:

    您的宏不太正确。改成这样:

    #define offSet(a,b,c,d) ( ((size_t) SIZE_B * SIZE_C * SIZE_D * a) + ((size_t) SIZE_C * SIZE_D * b) + ((size_t) SIZE_D * c) + d)
    

    基本上你的SIZE_X 移动了 1 个字母。

    我还建议在你的宏参数周围加上()

    #define offSet(a,b,c,d) ( ((size_t) SIZE_B * SIZE_C * SIZE_D * (a)) + ((size_t) SIZE_C * SIZE_D * (b)) + ((size_t) SIZE_D * (c)) + (d) )
    

    【讨论】:

      【解决方案3】:

      我似乎应该这样定义宏:

      #define offSet(a,b,c,d) ( ((size_t)  SIZE_B * SIZE_C *SIZE_D * a) + ((size_t)  SIZE_C *SIZE_D * b) + ((size_t) SSIZE_D * c) + d)
      

      【讨论】:

        【解决方案4】:

        在某些操作系统中,每个进程的内存分配存在限制。通常可以更改默认值。

        其他人,在调用 malloc 时甚至不分配实际内存,例如 Linux,以后尝试写入它时可能会失败,但我想这不是你的情况。

        尝试检查您是否可以控制系统上每个进程的最大分配内存。 希望你能找到答案,确实很有趣。

        一些阅读材料:

        http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory http://www.linux-mag.com/id/827/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-15
          相关资源
          最近更新 更多