0
votes

I came through this program to find length of a struct without using sizeof. I have some questions that I could not find answers.

  1. I cannot understand this step (char*)(p+1)-(char*)p) - why the pointer is type casted into char.

  2. I printed out size of each datatypes. So, the size of the structure should have been 3* size of int + size of float + size of char = 17. However, size of the struct is 20. Please explain how.

  3. Why the output is 5 for (float*)(p+1)-(float*)p).

Code:

#include<stdio.h>

struct sample
{
    int a,b;
    float c;
    char z;
    int k;
};

void main()
{
    struct sample *p;
    struct sample x;
    printf("size of struct w/o using sizeof: %d\n", (char*)(p+1)-(char*)p);

    printf("size of struct w/o using sizeof: %d\n", (float*)(p+1)-(float*)p);

    printf("size of struct using sizeof: %d\n", sizeof(struct sample));

    printf(" %d %d %d %d\n", sizeof(char), sizeof(int), sizeof(float), sizeof(x));

}

Output:

size of struct w/o using sizeof: 20
size of struct w/o using sizeof: 5
size of struct using sizeof: 20
1 4 4 20

4) Thank you for your answers. I have one more doubt.

code

struct sample
{
int a,b;
float c;
char z;
int k;
char s;
};

After padding, the size of this struct would be 24 bytes. Why printing this in float (float)((float*)(p+1)-(float*)p) does not give 5.8000 instead of 6.

3
For 1 and 3: what do you understand by p+1 without casting, i.e. how are you making this work at all? What is sizeof(char)? What is sizeof(float)? - Rup
Hint: For question 2, refer structure padding. - Santosh A
5 because the size is 5 floats (5 x 4 bytes) - Milind Dumbare
It isn't. It is typecast to pointer to char. - user207421

3 Answers

2
votes
  1. Converting in bytes will give you the difference in bytes between the two pointers

  2. Your structure gets padding to be aligned to 4 byte boundary. In your structure, the true sizes will be as following (including padding)

    struct sample
    {
         int a,b; // 8 bytes, 4 bytes each
         float c; // 4 bytes
         char d; // 4 bytes, 1 byte + 3 padding
         int k; // 4 bytes
    }
    
  3. Converting to float will give you the sizeof structure in floats (5 floats = 20 bytes)

1
votes
  1. Typecasted to (char*) because you want to print size in char (bytes). When you increment p, its going to increment by size of p. So (p+1)-p is the size of structure and (char *) help printing it in bytes.

  2. Read about structure alignment and padding

  3. 5 because this time its typecasted to (float *) because you want to print size in unit of float (4 bytes). When you increment p, its going to increment by size of p. So (p+1)-p is the size of structure and (float *) help printing it in number of floats (4 bytes).

0
votes
  1. Even though (char*)(p+1) - (char*)p) promises not to be using sizeof *p, it does implicitly so, because the pointers to p are multiplied by the size... of their respective type. Such is mentioned in C99: http://www.iso-9899.info/n1256.html#FOOTNOTE.91

  2. Many cpu architectures, including the intel x86 family of processors need to read their multi-byte integers at an address evenly divisible by their size, for example for 4-byte types the address must be evenly divisible by 4. That means, that when an array is created of your struct, the second element's ints must also be evenly divisible by 4 even if your char is at the end. That is why padding is added there and included in the struct's total size.

  3. This result is the size of the struct divided by the size of your float type. Because we now know that the size of your struct is 20, p+1 evaluates to the address 20 bytes after p, but then it is cast to float*, which divides the offset by the number of floats that fit into the interval.