1

I have a structure and want to pass it as an argument to printf by casting it to (char*). But I get gibberish output. I have learned that the pointer to the structure is also an pointer to its first member so I thought this typecast should work.

Why it doen't?

#include <stdio.h>
#include <string.h>

typedef struct str {
    char *s;
} str;

int main(void)
{
    str s;
    s.s = "Hello World!";
    printf("%s\n", (char *) &s);
}

Output:

(random bytes)
wohlstad
  • 12,661
  • 10
  • 26
  • 39
  • 2
    Try `*(char**)&s` instead. – n. m. could be an AI Mar 18 '23 at 11:57
  • @n.m. Works. Thank you. Thought it would be less writing needed. Why is `*(char**)&s` not the same as `(char*)` as this dereferences the "double pointer" to `char *` isn't it? – mortytheshorty Mar 18 '23 at 12:04
  • 2
    One of these things works and the other doesn't, so they cannot possibly be the same. `printf` wants a pointer that points to characters. `&s` (however you cast it) points to `s`, but `s` does not contain characters, it contains a pointer which points to characters. To get to that pointer, you need to dereference `&s`, suitably cast. – n. m. could be an AI Mar 18 '23 at 12:27
  • 1
    BIG AHHHH effect on me right now. Never realized a char pointer is interpreted like that. – mortytheshorty Mar 18 '23 at 12:32
  • @mortytheshorty `&s` in your original code is "address of `s`", which is also "address of `s.s`" because, as you noted, "the pointer to the structure is also an pointer to its first member". **But** `s.s` is a `char *` pointer, and taking an address of a `char *` results in a `char **`. `printf( "...%s...", ...)` expects to receive the **value** of a `char *`, not its address. – Andrew Henle Mar 18 '23 at 12:57
  • mortytheshorty, [Moral of the Story](https://www.vocabulary.com/dictionary/moral): avoid casting. It tends to hide problems. – chux - Reinstate Monica Mar 18 '23 at 16:10

2 Answers2

2

In this call of printf

printf("%s\n", (char *) &s);

the value of the expression &s points to the data member s of the object of the structure type. So the call of printf trying to interpret the memory occupied by the data member s itself as a string.

Instead you need to write

printf("%s\n", *(char **) &s);
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

It would work if the string was a part of the struct, not reference to it. If you change the code to:

typedef struct str {
    char s[24];
} str;

int main(void)
{
    str s = {"Hello World!"};
    printf("%s\n", (char *) &s);
}

It will work as you expected. https://godbolt.org/z/r17PPY9z3

I think you have a problem understanding the difference between a pointer and an array.

BTW avoid pointer punning.

0___________
  • 60,014
  • 4
  • 34
  • 74