Reputation: 127
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. 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];
if the compiler will accept arr[0][5] = 1;
anyway?
I'm using GCC compiler
Upvotes: 3
Views: 110
Reputation: 15566
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). You can enable the warning with -O2 -Wall -Wextra
if the variable is used or is declared volatile
.
With GCC and Clang it's sort of "safe" to do this; 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.
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.
Upvotes: 4
Reputation: 494
In my 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;
}
Upvotes: 0