tags:

views:

135

answers:

5

I have yet another newbie C question: Why does the first member of a struct return an adress not similar to the structs own pointer-adress when not initialized?

Example:

struct Metadata {
    int message_ID;
    //other members...
    //...
};

struct Metadata* baseMetadataPtr = (struct Metadata*) malloc(sizeof(struct Metadata)*100);

printf("baseMetadataPtr: %d\n", baseMetadataPtr);
//consoll says "baseMetadataPtr: 2636496"

printf("baseMetadataPtr->message_ID: %d\n", baseMetadataPtr->message_ID);
//consoll says "baseMetadataPtr->message_ID: 2621636"
+7  A: 

Your second printf call is wrong. It should be:

printf("baseMetadataPtr->message_ID: %p\n", &baseMetadataPtr->message_ID);
//         need to use %p for pointer ^     ^ need unary-& operator

As written right now, the integer value of message_ID is being printed. You need to take the address of baseMetadataPtr->message_ID. Also note that if you want to print a pointer, you should use the %p format specifier, not %d (which prints an integer).

The address of the first data member of a struct-type object will always be the same as the address of the struct-type object itself. This is guaranteed because no padding is permitted at the beginning of a struct (padding is permitted between data elements or at the end of the struct, though).

James McNellis
DoggyDoo
Err..`message_ID` is not being interpreted as a pointer until he uses the `%p` specifier. Right now `baseMetadataPtr` is being interpreted as a decimal integer...
dmckee
@DoggyDoo: It is whatever garbage data was in the block of memory to which the pointer returned from `malloc` points.
James McNellis
@dmckee: Oops; missed that one--thanks.
James McNellis
For extra conformance, cast every pointer to `(void *)` when printing with `%p`.
schot
A: 

This prints the memory address of the pointer:

printf("baseMetadataPtr: %d\n", baseMetadataPtr); 

and this prints the memory address of the variable inside the struct:

printf("baseMetadataPtr->message_ID: %d\n", &baseMetadataPtr->message_ID); 

And that's why they are not neighbors.

karlphillip
A: 

baseMetadataPtr->message_ID prints the value of the variable message_ID. Since you have not initialized it, it is containing garbage. To print its address you need to do &baseMetadataPtr->message_ID. Also, you need to use the format specifier %p to print pointer values.

Naveen
A: 

The first printf() prints the current value of the pointer, IE, what address it is pointing.

The second printf prints the value of the Metadata member message_ID.

To get what you want, try: printf("baseMetadataPtr->message_ID: %d\n", &baseMetadataPtr->message_ID);

dicroce
+1  A: 

I like drawings. They help me "see" stuff

struct Metadata *baseMetadataPtr;
baseMetadataPtr = malloc(100 * sizeof *baseMetadataPtr);

With that, and assuming a linear memory (the boxes below), and ignoring the space requirements for the different objects, we have

|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|...|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|...
   ^^^^^^^ baseMetadataPtr
  (of type (struct Metadata *))

   ******* ===========================>
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|...|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|...
   ^^^^^^^ baseMetadataPtr             ^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^ ^^ ...
  (of type (struct Metadata *))        *baseMetadataPtr (struct Metadata)
                                               *(baseMetadataPtr+1)
                                                      baseMetadataPtr[2]

And, zooming in on the part on the left

   *baseMetadataPtr
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|...
   ^^^ Message_ID (type (int))
       ^^^^^^^ Message_Len (type (size_t))
               ^^^^ ... other members, followed by another object of type (struct Metadata)
pmg