I came across a concept which some people call a "Struct Hack" where we can declare a pointer variable inside a struct, like this:
struct myStruct{
int data;
int *array;
};
and later on when we allocate memory for a struct myStruct
using malloc
in our main()
function, we can simultaneously allocate memory for our int *array
pointer in same step, like this:
struct myStruct *p = malloc(sizeof(struct myStruct) + 100 * sizeof(int));
p->array = p+1;
instead of
struct myStruct *p = malloc(sizeof(struct myStruct));
p->array = malloc(100 * sizeof(int));
assuming we want an array of size 100.
The first option is said to be better since we would get a continuous chunk of memory and we can free that whole chunk with one call to free() versus 2 calls in the latter case.
Experimenting, I wrote this:
#include<stdio.h>
#include<stdlib.h>
struct myStruct{
int i;
int *array;
};
int main(){
/* I ask for only 40 more bytes (10 * sizeof(int)) */
struct myStruct *p = malloc(sizeof(struct myStruct) + 10 * sizeof(int));
p->array = p+1;
/* I assign values way beyond the initial allocation*/
for (int i = 0; i < 804; i++){
p->array[i] = i;
}
/* printing*/
for (int i = 0; i < 804; i++){
printf("%d\n",p->array[i]);
}
return 0;
}
I am able to execute it without problems, without any segmentation faults. Looks weird to me.
I also came to know that C99 has a provision which says that instead of declaring an int *array
inside a struct, we can do int array[]
and I did this, using malloc()
only for the struct, like
struct myStruct *p = malloc(sizeof(struct myStruct));
and initialising array[] like this
p->array[10] = 0; /* I hope this sets the array size to 10
and also initialises array entries to 0 */
But then again this weirdness where I am able to access and assign array indices beyond the array size and also print the entries:
for(int i = 0; i < 296; i++){ // first loop
p->array[i] = i;
}
for(int i = 0; i < 296; i++){ // second loop
printf("%d\n",p->array[i]);
}
After printing p->array[i]
till i = 296
it gives me a segmentation fault, but clearly it had no problems assigning beyond i = 9
.
(If I increment 'i' till 300 in the first for loop above, I immediately get a segmentation fault and the program doesn't print any values.)
Any clues about what's happening? Is it undefined behaviour or what?
EDIT: When I compiled the first snippet with the command
cc -Wall -g -std=c11 -O struct3.c -o struct3
I got this warning:
warning: incompatible pointer types assigning to 'int *' from
'struct str *' [-Wincompatible-pointer-types]
p->array = p+1;