2

I saw the following fragment of C code in a text book and it's working properly... But I do not understand the output and why is it working properly, because it looks wrong:

#include <stdio.h>

int main()
{

    struct {
        int x,y;
    } s[4] = {{10,20},{15,25},{8,75},{6,2}};
    int *i;
    i=s;

    clrscr();
    printf("\n%d",s[i[7]].x);
    printf("\n%d",i[i[1]-i[2]]);
    printf("\n%d",i[s[3].y]);
    printf("\n%d",(s+1)->x+5);
    printf("\n%d",s[i[0]-i[4]].y + 10);
    printf("\n%d",++i[i[6]]);
    getch();

    return 0;

}

Also I do not understand how we can assign an integer pointer to s in the statement

i=s;
10
  • Which line are you concerned about? Commented Jun 16, 2012 at 16:22
  • Also, this code doesn't compile. See e.g. ideone.com/7pTKA. Commented Jun 16, 2012 at 16:23
  • The first two printf statements..I Dont understand how they mean. Commented Jun 16, 2012 at 16:24
  • Maybe ideone uses gcc.But it does get compiled on TC Commented Jun 16, 2012 at 16:24
  • If we remove getch() for gcc then it would compile Commented Jun 16, 2012 at 16:25

4 Answers 4

2

Also i do not understand how we can assign an integer pointer to s in the statement: i=s;

It is simple, you can't in C without a cast. You compiler is kind enough to accept such a program but other compilers have the right to refuse to compile the program.

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

10 Comments

But in such a condition shouldn't i be getting a garbage output?
Each printf above prints some or other element of array
@arpitsolanki: This code does not compile cleanly in GCC, and that is the problem.
@ouah: This one's so basic, you don't even need -Wall!
@arpitsolanki: Any behaviour you're observing is undefined behaviour.
|
1

As far as the pointer assignment:

To take a comment from below:

"the memory layout of an array of ints and an array of struct composed solely by ints is the same"

The reason pointer types must be defined are because the compiler must know the size of the data the pointer is pointing to. Integers have a size of 4 byes, while this struct would have a size of 8 bytes. When the program tries to access the memory at location s[1], the compiler knows that the program wants the data 8 bytes after s[0], where i[1] would want the data only 4 bytes after i[0].

s is an array of structs(with two members of type int), i is a pointer to an int. Since the first element of s is a struct of 2 ints, i = s assigns the address of the first member of the first element of s to i.

i = &s[0] is the same assignment.

If s[0] started at 0x00, it's first member has the address 0x00, while it's second member has the address 0x04. s[1] would start at 0x08, the struct at that location has a second member with the address 0x0C.

With i = s, i[0] has the address 0x00, while i[1] has the address 0x04, the second member of the first element of s. i[2] has the address 0x08, the first member of the second struct in the array, i[3] has the address 0x0C, the second member of the second struct in the array. And so on...

  { 10, 20 } { 15, 25 } { 8, 75 } { 6, 2 }
s:|    0    |     1    |    2    |   3   |
i:| 0 |  1  |  2 |  3  |  4 | 5  | 6 | 7 |

i now points at the first integer (out of all 8).

i[0] = 10

i[7] = 2

The first printf statement is interpreted as follows: Since i[7] = 2, then we have s[2] referring to the pair {8,75}, that has the x value 8.

The pointers indeed are incompatible, compiling with gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) produces the following warning:

test.c: In function ‘main’: test.c:10: warning: assignment from incompatible pointer type

However, the program does compile and product the output:

8 75 15 20 85

16 Comments

also wouldn't s be an array of structures?
@arpitsolanski: for C there's no difference
@OliCharlesworth: i contains the value of the pointer of the first memory location of s. So yes, it's a pointer to a struct!
@vanDarg if i[0]=10 and 1[7]=2 then how do you explain the output of first printf?
@ouah and indeed it raises a warning. Nontheless, the memory layout of an array of ints and an array of struct composed solely by ints is the same.
|
1

Adding a little : in C I follows the trick when its comes situation like this : whenever you see like this #type# s[p], s is a pointer of #type# type, and s[p] is another way of writing *(s+p). Hence ('i' assigned the base address of the array) for example -- i[i[1]-i[2]] is i[(*(i+1)) - (*(i+2))] => i[20 - 15] => i[5] => *(i+5) => 75.

Also note,

1) Internal padding may be used in allocating storage for struct. for ex. a struct with two ints and one char is not necessarily will take 4+4+2 = 10 bytes consecutively, there may be internal padding. However this struct with two ints only doesn't use internal padding.

2) Warning will be given as incompatible pointer is assigned by most compilers.

3)'i' was alloted the base address of array of structures with no internal padding, thus this carefully designed code magically works.

3 Comments

Can you throw some light on the internal padding of structures..exactly what is it?
since computer reads/writes to memory addresses in word sized chunks, so structures having different data types may need internal padding while storing data otherwise some word read would contain a portion of data. Ex. : (assume)if struct of three char (3 * 8 = 24 bits) and one int (16*1 = 16 bits) will be internally padded if word size is 32 bit, i.e. last 8 bits of first word will be empty.
this is low level compiler option that you don't have to care, but just remember that never believe that sum of sizeof data types in the struct is the size of the struct.
0

The compiler stores the data of s[4] in linear memory, such as 10,20,15,25,8,75,6,2. i[7] is equal to 2.It is just a trick like the following example.

there is a structure like this:

struct block{
int a;
int b;
};

struct block item;

If I know the address of item->b, how can I know the address of item.

The answer is using the address of item->b minus ((struct block *)0)->b.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.