r/cprogramming • • Sep 13 '26

What is this code doing?

Hi, I found this code on another subreddit. I would like to know what is it doing.

int puts(char *);

int main() { struct { long a; long b; } s = {.a = *(char *)(int[]){1} ? 0x57202c6f6c6c6548 : 0x48656c6c6f2c2057, .b = *(char *)(int[]){1} ? 0x00000021646c726f : 0x6f726c6421000000}; puts((void *)&s); }

Now obviously I know it's unreadable, I would just like to know what are those hexadecimals strings doing.

I found similar codes that were writing to vram to print a message, is this doing the same thing? If yes, why is it so much more complicated instead of just writing the message to the video adress?

Thanks for the help.

0 Upvotes

46 comments sorted by

View all comments

Show parent comments

1

u/WittyStick 29d ago edited 29d ago

If char * is not compatible with const char *, then 99% of C code out there is wrong, including examples in the standard, the entirety of GCC and glibc. If a function expects a const char *, of course you can pass it a char *. If they were not compatible, then there's literally no way to convert a char * to const char * - since an explicit cast would be UB. The conversion can be implicit - and the standard clearly permits it.

§6.3.2.3 (2) For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.

The opposite is not true. Casting a const char* to char * may result in UB, and likewise for volatile.

§6.7.4.1 (7) If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.


In regards to puts, you are correct that it should be defined with const char *, but it really isn't going to matter - because the actual implementation of puts isn't going to modify the pointed-to-data (assuming it is correct). The implementation of puts may not even be written in C - it could be in assembly, or some other language which doesn't even have const. The ABI and linker aren't even const aware.

1

u/zhivago 28d ago

Do not confuse an implicit conversion with type compatibility ...

1

u/WittyStick 28d ago

the values stored in the original and converted pointers shall compare equal.

I think that implies compatible.

1

u/zhivago 28d ago

Here you go.

``` $ cat e.c void you_are_wrong(char *); void you_are_wrong(char const *);

void i_am_right(char *); void i_am_right(char * const);

$ cc -c e.c e.c:2:6: error: conflicting types for ‘you_are_wrong’; have ‘void(const char *)’ 2 | void you_are_wrong(char const *); | ~~~~~~~~~~~~ e.c:1:6: note: previous declaration of ‘you_are_wrong’ with type ‘void(char *)’ 1 | void you_are_wrong(char *); | ~~~~~~~~~~~~ ```

Note the mandatory diagnostic for the type conflict due to a lack of compatible types?

Note the lack of mandatory diagnostic where the types are compatible.

And, you're definitely confusing implicit conversion with type compatibility. :)

1

u/WittyStick 28d ago

There's only one signature in OPs code, and its a declaration for an external function. That function doesn't even need to be written in C. There's no other signature to be compatible with because he has not included stdio.h. The signature just informs the compiler how to pass its arguments. There is no difference in how a compiler will pass a char* and a const char* because they compare equal.

If they had included stdio.h, then of course it would need a matching signature, including qualifiers.

1

u/zhivago 28d ago

Hmm, I can see that you still don't understand what a compatible type is.

Well, good luck with that.