0

i have a query on following C programme

code:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    struct a
    {
        char arr[10];
        int i;

        float b;
    }v[2];

    printf("\n %d   %d  %d  \n",v[0].arr, &v[0].i, &v[0].b);
    printf("\n %d   %d  %d  \n",v[1].arr, &v[1].i, &v[1].b);


    printf("\nHello world!\n");
    return 0;
}

Output:

 2686712   2686724  2686728

 2686732   2686744  2686748

 Hello world!

Question: v[0].arr == 2686712 and arr[10] that has size 10 bytes &v[0].i <<<< this address should start immediately after the array .. since array is of 10 bytes .. the address of &v[0].i should start from 2686712+10 i.e 2686722 why is &v[0].i == 2686724 and not 2686722

Jeff Loughlin
  • 4,134
  • 2
  • 30
  • 47
  • Memory is aligned so that the CPU can read it in blocks. (Assuming this is a 32-bit machine) Despite only 10 byte are being in use, 12 bytes alignment is preferred so that the next value (which happens to be a int) will be read as an int more quickly (without any arithmetics) and a (4's multiple) bytes groups. – SGM1 Mar 24 '14 at 17:05
  • possible duplicate of [What exactly is an 'aligned pointer'?](http://stackoverflow.com/questions/4322926/what-exactly-is-an-aligned-pointer) – n. m. could be an AI Mar 24 '14 at 17:06

5 Answers5

3

The compiler is allowed insert padding in between members of a struct or at the end but not at the beginning. From the draft C99 standard section 6.7.2.1 Structure and union specifiers paragraph 13 which says (emphasis mine):

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

and paragraph 15:

There may be unnamed padding at the end of a structure or union.

by using %d format specifier for a pointer you are invoking undefined behavior you should be using %p.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
3

The compiler pads structure members to keep things aligned properly for each data type.

See this link for information on how structure padding actually works. There is a lot of very detailed information there. See also this link for alignment information specific to the intel processor for the various data types.

In essence, because you have a 10-byte char array followed by an int, the compiler has padded the char array with an extra 2 bytes so that the int will be aligned properly on a 4-byte boundary (that is, an address evenly divisible by 4).

It is as if you declared your structure like this:

struct a
{
    char arr[10];
    char _padding[2];
    int i;
    float b;
};

Out of habit, I usually allocate char arrays with sizes that are evenly divisible by 4. That way the compiler doesn't have to do it for me, and it makes it easier to visualize what the data structure looks like in memory.

Jeff Loughlin
  • 4,134
  • 2
  • 30
  • 47
  • Windows align on byte boundaries for all data types. – JackCColeman Mar 24 '14 at 17:46
  • @JackCColeman: I sure hope that's not true. That would cause a major performance problem, since the intel processor wants data to be naturally aligned... See http://software.intel.com/en-us/articles/coding-for-performance-data-alignment-and-structures for more info. – Jeff Loughlin Mar 24 '14 at 17:50
  • from what I can tell, the C libs for windows define/allow LONG on byte boundaries. Just browsed the article, my response, is this is old-time technology, are processors really constrained this way? With up to three levels of cache word boundaries seem irrelevant?? – JackCColeman Mar 24 '14 at 17:56
  • @JackCColeman: Newer processors take less of a hit, but it still does matter to some extent - See http://lemire.me/blog/archives/2012/05/31/data-alignment-for-speed-myth-or-reality/ where the author did some testing that still shows a 10% performance penalty even with recent processors (that was in 2012). – Jeff Loughlin Mar 24 '14 at 18:08
  • I would guess that the attitude is that the effort required to align on "correct" boundaries is so processor specific that it isn't worth the headaches at the software level, especially when shipping a product to many PCs (for example, what happens if the customer upgrades a CPU but nothing else?) – JackCColeman Mar 24 '14 at 18:12
  • @JackCColeman: But Windows only runs on Intel architectures. It would be foolish of them to design a compiler that didn't get the best performance out of the machine. Even gcc, which supports 41 different processor architectures (at last count), generates code with the proper alignment for each of them. I would be extremely surprised if your assertion about byte-alignment under Windows were correct... – Jeff Loughlin Mar 24 '14 at 18:22
  • get thyself to a C compiler from Microsoft installed on a Windows machine. Foolishness doesn't count when making a business decision. That is, so what if the application running on a PC runs 10% slower? If the customer (maybe 0.5% of all customers, at most) needs that performance then they will compile it using a compiler that was more expensive to build and made the builders less money. – JackCColeman Mar 24 '14 at 18:29
  • @JackCColeman: Normally I wouldn't question an assertion that Microsoft would do something stupid for business reasons...however, I just compiled the OP's code with Visual Studio 2012 and I do indeed see the data structure getting padded with an extra 2 bytes in the generated code. – Jeff Loughlin Mar 24 '14 at 18:54
  • like I said, I think microsoft C allows LONG, etc. to be defined on a byte boundary. If a structure is built in a way that aligns datatypes on their "correct" boundaries, then that is ok. – JackCColeman Mar 24 '14 at 20:45
2

First: You shouldn't use %d to print a pointer with printf but %p.

Second: Only the first element of a struct is guaruanteed to start at the adress of the structure. Any other member can have padding bytes inserted, depending on the compiler and architecture requirements.

Devolus
  • 21,661
  • 13
  • 66
  • 113
1

Most compilers will pad your struct elements by default to the member size. Thus there will be two padding bytes after arr.

Use struct {...} __attribute__(packed); if you wish to have a fully packed struct.

Sergey L.
  • 21,822
  • 5
  • 49
  • 75
0

On your system 4-byte alignment happens.

and

"int" and "float" will take 4-byte "char" will 1-byte

1)in your question your structure you are wasting 2-byte because of sequence

struct a {

    char arr[10];
    int i;
    float b;

}v[2];

ANS::2)My solution is just change sequence of "char arr[10]", put it in last


struct a

{

     int i;

    float b;

    char arr[10];


}v[2];

Now if you will print address then it will print according your understanding...

3)Memory alignment can be changed as per your requirement which is provided by Compiler using "PRAGMA" search "PRAGMA" on google to use.

Vinod Patidar
  • 372
  • 1
  • 4
  • 12