访问2D数组的正确方法-C

问题描述 投票:3回答:2

假设我有这个动态分配的2D数组:

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

但是,我发现如果我这样做:

arr[0][5] = 1;

编译器不会抱怨,至少使用valgrind进行测试时,它也不会抱怨。除非我尝试访问超出已分配空间大小的空间,否则不会这样做。

我发现自动数组也会发生同样的情况:

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

我的问题是:例如,声明:int arr[3][2];编译器是否仍将接受arr[0][5] = 1;是什么意思?

我正在使用GCC编译器

c arrays multidimensional-array
2个回答
0
投票

在我的PC 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;
}

3
投票

通常,不要超出已分配的内存范围。

Clang默认会警告两个示例,而GCC不会警告两个示例,而不会实际使用变量(这是无效代码消除器的错误)。如果使用变量或将其声明为-O2 -Wall -Wextra,则可以使用volatile启用警告。

但是,这是(当然)未定义的行为,所以它总是一个坏主意。

一种(可能)等效的分配方式是:

arr[2][1] = 1;

这是基于数组元素顺序存储在内存中的假设。

我的建议:

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

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

保证安全。

© www.soinside.com 2019 - 2024. All rights reserved.