简体   繁体   English

访问二维数组的正确方法 - C

[英]Correct way to access to 2D Array - C

let's imagine I have this dynamically allocated 2D array:让我们想象一下我有这个动态分配的二维数组:

//Example of a 3 row * 2 columns int array
int (*arr)[2] = malloc(sizeof(int[3][2]));

However, then I found that if I do:但是,后来我发现如果我这样做:

arr[0][5] = 1;

The compiler does not complain, and at least testing with valgrind, it neither complains.编译器没有抱怨,至少用 valgrind 测试,它也没有抱怨。 It doesn't unless I try to access to a space which exceeds the size of the allocated space.除非我尝试访问超过分配空间大小的空间,否则不会。

I found that the same happens for automatic arrays:我发现自动数组也会发生同样的情况:

int arr[3][2];
arr[0][5] = 1; //Code works without errors 

My question now is: what's the point of having for example declared: int arr[3][2];我现在的问题是:例如声明有什么意义: int arr[3][2]; if the compiler will accept arr[0][5] = 1;如果编译器会接受arr[0][5] = 1; anyway?反正?

I'm using GCC compiler我正在使用 GCC 编译器

In general, don't write past the bounds of memory that you've allocated.一般来说,不要超过你分配的内存边界。

Clang will warn about both examples by default, while GCC will warn about neither without the variables actually being used (that's the fault of the dead code eliminator).默认情况下,Clang 会警告这两个示例,而 GCC 会在没有实际使用变量的情况下警告这两个示例(这是死代码消除器的错误)。 You can enable the warning with -O2 -Wall -Wextra if the variable is used or is declared volatile .如果使用变量或声明为volatile您可以使用-O2 -Wall -Wextra启用警告。

With GCC and Clang it's sort of "safe" to do this;使用 GCC 和 Clang 这样做是“安全的”; the same thing will happen each time.每次都会发生同样的事情。

However, this is undefined behavior, so it's a bad idea.然而,这是未定义的行为,所以这是一个坏主意。 It's entirely valid for a program that does this to make your computer grow legs and walk away.对于执行此操作以使您的计算机长腿并走开的程序来说,这是完全有效的。

An equivalent way of doing the assignment would be:进行分配的等效方法是:

arr[2][1] = 1;

This goes based on the assumption that the array elements are stored sequentially in memory.这是基于数组元素按顺序存储在内存中的假设。

So, &arr[5][0] is technically the same as &arr[2][1] , but it shouldn't be used.因此, &arr[5][0]在技​​术上与&arr[2][1] ,但不应使用它。

My advice:我的建议:

int arr[3][2];
int x, y;

for( x = 0; x < 3; x++ )
    for( y = 0; y < 2; y++ )
        arr[x][y] = x * y;

This is guaranteed to be safe.这保证是安全的。

In my pc Gcc 8.1.0在我的电脑 Gcc 8.1.0

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

int main(){



    int i,j;
    int (*arr)[2] = malloc(sizeof(int[3][2]));
    printf("%p %d %d\n",arr,sizeof(int),sizeof(int[3][2]));
    //in my computer print 
    //00C63E38 4 24
    //legal memory from 00C63E38~00C63E4C 
    for(i=0;i<3;i++){
        for(j=0;j<2;j++){
            printf("%p ",&arr[i][j]);
        }
        printf("\n");
    }
    //00C63E38 00C63E3C 
    //00C63E40 00C63E44 
    //00C63E48 00C63E4C
    printf("------------------\n");
    for(i=0;i<3;i++){
        for(j=0;j<2;j++){
            printf("%p ",*(arr+i)+j);
        }
        printf("\n");
    }
    //00C63E38 00C63E3C 
    //00C63E40 00C63E44 
    //00C63E48 00C63E4C
    //So arr[i][j] is equel *(arr+i)+j
    printf("-------------\n");
    for(i=0;i<6;i++){
        printf("%p ",arr+i);
        printf("\n");
    }
    printf("-------------\n");
    //jump 4*2 pointer address per loop from 00C63E38
    //00C63E38 
    //00C63E40
    //00C63E48
    //00C63E50 
    //00C63E58
    //00C63E60
    for(i=0;i<6;i++){
        printf("%p ",arr[0]+i);
        printf("\n");
    }
    //jump 4 pointer address per loop from 00C63E38
    //00C63E38
    //00C63E3C 
    //00C63E40
    //00C63E44 
    //00C63E48
    //00C63E4C
    free(arr);

    return 0;
}

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

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