tags:

views:

105

answers:

4

Hi everybody, thanks for your support for solving my previous problems. Now I'm studying self referential structures. I have written the following code:

#include <stdio.h>

int main()
{
system("clear");
struct node
{
 int x;
  struct node *next;
} p1;

printf(" \nthe address of node1 = %u",& p1);

printf(" \n\nthe size of node 1 = %d",sizeof( p1));
printf("\n\n the size of info part = %d",sizeof(p1.x));
printf("\n\n the size of pointer part = %ld",sizeof(p1.next));
printf("\nthe size of node is = %d\n",sizeof(struct node));
return;
}

The program compiled with few warning like:

warning: format ‘%u’ expects type ‘unsigned int’, but argument 2 has type ‘struct node *’

Every time I do something with pointer such warning is generated. What is the problem? I don't know that. Can anybody explain why it happen on Linux (specially)?

My second question is as I run the program it shows the size of structure 16 while int take 4 byte (Ubuntu 10) & pointer is of 8 byte. Then why it shows size of structure 16 byte?

+4  A: 

In C99, use '%zd' to print size_t.

Elsewhere, simply cast the result of sizeof() to int; you aren't going to overflow anything.

To print pointers in C99, if you don't like the default format from %p:

#include <inttypes.h>

printf("Pointer = 0x%" PRIXPTR "\n", (uintptr_t)&something);

The type uintptr_t is guaranteed to be big enough to hold pointers.

And your size issue is because of alignment requirements; 8-byte pointers must be 8-byte aligned for optimal performance (on some machines, to avoid crashes). So, the structure must be a multiple of 8 bytes long, and 16 is the smallest multiple of 8 that is larger than 12 bytes. You'll also have some padding between the two parts of your structure - 4 bytes of padding, in fact. You could use the offsetof() macro from <stddef.h> to demonstrate that.

Jonathan Leffler
`sizeof()` or `sizeof`? `++(i)` or `++i`? Nice trick about formatting pointer values with `intptr_t` by the way. +1
schot
@schot: I was simply indicating the `sizeof()` operator - which obviously takes an argument, the thing that it is to return the size of. I know it does not always need parentheses around the argument, but since it always works with parentheses around the argument, I always use parentheses around the argument.
Jonathan Leffler
@Jonathan: 'twas but a minor jest. `return (0);`
schot
@Jonathan: when sizeof "needs" parenthesis, they are needed for the type itself (like a cast): `sizeof object` ... `sizeof (int)object` ... `sizeof (int)`
pmg
A: 

%p is the format string for a pointer, which is what you're passing to the first printf.

cHao
A: 

Many CPU architectures can not handle, or are very inefficient at handling arbitrary addresses.

Your architecture, which I guess is x86_64, wants to access memory in at least 8 byte chunks.

So, 12 bytes equals one and a half 8 byte chunk - not good. What then happens is, the compiler pads out the structure with dummy data at the end until it fits in even 8 byte chunks, in this case 4 bytes extra, for a total of 16 bytes.

The same goes for different processors, but with different alignments. Some CPUs even work fine without alignment at all, but most modern processor works best with alignment.

As others have noted, use for example %p for pointer printing.

For the size_t printfs, use %lu and cast to (unsigned long) if you can not use C99 and %zd.

Amigable Clark Kant
A: 

This program works fine under LINUX distribution Fedora12. It yields the correct output.

Elcid