0

I'm trying to access the next element in dynamically allocated by adding the size of placeholder array to the first element. Size of placeholder array is 4 bytes, so if I add 4 bytes to it first element with address 2147549788, I should be looking at next memory location 2147549792. But, instead I'm looking at an address in 16 bytes 2147549804. If I read the address of array elements directly I get the right address. Wondering why adding size of placeholder gives different results ? Also, if I access the location of second element outside the for loop, the location is off by another 16 bytes i.e 2147549820

#include "stdio.h"
#include "time.h"
#include <stdlib.h>
#include <string.h>

typedef struct Section {
    int numOfStudents;
} Section;

typedef struct School {
    int schoolId;
    Section sections[1]; //placeholder
} School;

int main(void) 
{
    School *schoolA_p;  
    Section section1;
    int sizeOffset = 0;
    int i,sectionSize;

    int sizeOfSchool = sizeof(School) - sizeof(Section) + (sizeof(Section)*2);
    schoolA_p = (struct School *) malloc(sizeOfSchool);

    for(i=0;i<2;i++)
    {
        sectionSize = sizeof(Section);

        printf("\nsize of section = %d\n", sizeof(Section));
        printf("Number of bytes to add to first element to access the next element = %d\n", sizeOffset);
        printf("In Loop Location of schoolA_p->sections[%d]= 0x%lx\n",i, &(schoolA_p->sections[0]) + sizeOffset);

        sizeOffset += sectionSize;
    }

    printf("\n Location of schoolA_p->sections[0]= 0x%lx\n",&(schoolA_p->sections[0]));
    printf("\n Location of schoolA_p->sections[1]= 0x%lx\n",&(schoolA_p->sections[1]));

    printf("\n Outside of lopop Location of schoolA_p->sections[0]= 0x%lx\n", &(schoolA_p->sections[0])+ sizeOffset);

    free(schoolA_p); 
    return 0;
}
5
  • On the inloop call, you forgot the &. schoolA_p->sections[0] -> &schoolA_p->sections[0] . Commented Sep 26, 2015 at 16:44
  • @jas can you share the o/p you are getting? Commented Sep 26, 2015 at 16:48
  • 4
    Assuming that the forgotten "&" is a typo in the question, aren't you just forgetting that C pointer arithmetic takes into account the size of the items? So p + 4 steps 4 data objects forward, not 4 bytes. Commented Sep 26, 2015 at 16:53
  • You should use format specifier %p to print a pointer, which should be cast to void* such as printf("%p",(void*)ptr) Commented Sep 26, 2015 at 17:06
  • I forgot &. But I guess the issue was pointer arithmetic, I was assuming it to be 4 bytes forward. Didn't realise it will be 4 data objects forward. Thanks! Commented Sep 26, 2015 at 17:08

2 Answers 2

2

Pointer arithmetic works like this: If p is a pointer to an array element a[n], then p + i is a pointer to a[n + i]. In other words, pointer arithmetic moves in units of whatever base type the pointer is declared as, not bytes.

Sign up to request clarification or add additional context in comments.

Comments

1

C pointer arithmetic takes into account the size of the data pointed to when you increment a pointer.

So if p is a pointer to data of 4 bytes, p + 1 calculates the address 4 bytes after p.

In other words, your doing too much work. C does this bookkeeping for you, and that's why you're getting incorrect results.

As a side note, this is why you cannot use pointer arithmetic on void* pointers. The size of the data pointed to is not specified.

2 Comments

Side side note: gcc allows arithmetic on void * as an extension (treating it like char *).
@melpomene I didn't know that. That's pretty interesting actually. It seems really unsafe, and I would never recommend doing that, but C is not really a "safe" language anyway.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.