Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can i use "int" as my dynamic array inside a struct?

In general, i'm trying to allocate values of first.a and first.b to a array's in struct secon.

typedef struct {
    int a;
    int b;
} firs; 

//secon is my struct which contains dynamic array
//can i use int here ? 

typedef struct {
    int *aa;
    int *bb;
} secon;

//pointer to secon intialised to NULL;
secon* sp=NULL;

int main() 
{
    firs first;

    //plz assume 2 is coming from user ;
    sp=malloc(sizeof(secon)*2);

    //setting values 
    first.a=10;
    first.b=11;


    /* what i'm trying to do is assign values of first.a and first.b to my 
        dynamically created array*/

    /* plz assume first.a and first.b are changing else where .. that means ,not 
        all arrays will have same values */


    /* in general , i'm trying to allocate values of first.a and first.b
        to a array's in struct second. */

    for(int i=0; i<2; i++) {
        *( &(sp->aa ) + (i*4) ) = &first.a;
        *( &(sp->bb ) + (i*4) ) = &first.b;
    }

    for(int i=0; i<2; i++) {
        printf("%d %d \n", *((sp->aa) + (i*4) ),*( (sp->bb) +(i*4) ) );
    }

    return 0;
}

MY output :

10 11 

4196048 0

Problems with my code: 1. whats wrong with my code? 2. can i use int inside struct for dynamic array? 3. what are the alternatives? 4. why am i not getting correct answer?

like image 890
bbcbbc1 Avatar asked May 20 '26 04:05

bbcbbc1


2 Answers

Grigory Rechistov has done a really good job of untangling the code and you should probably accept his answer, but I want to emphasize one particular point.

In C pointer arithmetic, the offsets are always in units of the size of the type pointed to. Unless the type of the pointer is char* or void* if you find yourself multiplying by the size of the type, you are almost certainly doing it wrong.

If I have

int a[10];
int *p = &(a[5]);
int *q = &(a[7]);

Then a[6] is the same as *(p + 1) not *(p + 1 * sizeof(int)). Likewise a[4] is *(p - 1)

Furthermore, you can subtract pointers when they both point to objects in the same array and the same rule applies; the result is in the units of the size of the type pointed to. q - p is 2, not 2 * sizeof(int). Replace the type int in the example with any other type and the p - q will always be 2. For example:

struct Foo { int n ; char x[37] ; };
struct Foo a[10];
struct Foo *p = &(a[5]);
struct Foo *q = &(a[7]);

q - p is still 2. Incidentally, never be tempted to hard code a type's size anywhere. If you are tempted to malloc a struct like this:

struct Foo *r = malloc(41); // int size is 4 + 37 chars

Don't.

Firstly, sizeof(int) is not guaranteed to be 4. Secondly, even if it is, sizeof(struct Foo) is not guaranteed to be 41. Compilers often add padding to struct types to ensure that the members are properly aligned. In this case it is almost a certainty that the compiler will add 3 bytes (or 7 bytes) of padding to the end of struct Foo to ensure that, in arrays, the address of the n member is aligned to the size of an int. always always always use sizeof.

like image 108
JeremyP Avatar answered May 21 '26 20:05

JeremyP


It looks like your understanding how pointer arithmetic works in C is wrong. There is also a problem with data layout assumptions. Finally, there are portability issues and a bad choice of syntax that complicates understanding.

I assume that wit this expression: *( &(sp->aa ) + (i*4) ) you are trying to access the i-th item in the array by taking address of the 0-th item and then adding a byte offset to it. This is wrong of three reasons:

  1. You assume that after sp[0].aa comes sp[1].aa in memory, but you forget that there is sp[0].bb in between.
  2. You assume that size of int is always 4 bytes, which is not true.
  3. You assume that adding an int to secon* will give you a pointer that is offset by specified number of bytes, while in fact it will be offset in specified number of records of size secon.

The second line of output that you see is random junk from unallocated heap memory because when i == 1 your constructions reference memory that is outside of limits allocated for *secon.

To access an i-th item of array referenced by a pointer, use []:

secon[0].aa is the same as (secon +0)->aa, and secon[1].aa is equal to (secon+1)->aa.

like image 31
Grigory Rechistov Avatar answered May 21 '26 21:05

Grigory Rechistov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!