0

I hope this isn't a stupid question, but say I want to create a char* in C called "Hello World", using only a double. I want to do this by abusing type confusion, so that in one file I might have something like this:

char test[12];    
int main() {
    printf("%s\n", test);
}

and in the other file I'd have this:

double test = some_random_double;

So my issue is therefore in picking a double that converts into the Ascii string "Hello World".

Are there any suggestions? I thought I would go backwards and convert the ascii string into hex or binary, and then try converting said hex/binary into a float format, but I can't figure out how to do so.

Clerryup
  • 37
  • 2
  • 4
    A `double` on most OSes offers you only eight bytes, and one of them is consumed by the NUL terminator, so you can only print a seven-character message. "Hello World" is too long for that. – zwol Feb 28 '16 at 02:28
  • 1
    However, hint: `union { char s[8]; double d; } u; strcpy(u.s, "1234567"); printf("%a\n", u.d);` – zwol Feb 28 '16 at 02:29
  • @zwol Endianness will make a difference – nalzok Feb 28 '16 at 02:35
  • @zwol Thank you! :) What does %a mean? – Clerryup Feb 28 '16 at 02:43
  • 2
    There is actually no solution to this question that does not involve undefined behaviour. What is the purpose of the question, other than (say) writing obfuscated code that will only work with some compilers? – Peter Feb 28 '16 at 02:54
  • You would need to declare `test` to be `extern` in the first file. And on most architectures, you would need to make `test` an array of `double` for it to be large enough. – Tom Karzes Feb 28 '16 at 03:05
  • 1
    @Clerryup: `%a` produces the hexadecimal syntax for floating point values. It is more effective to convert back to the same exact bit representation than the decimal format. – chqrlie Feb 28 '16 at 03:16

1 Answers1

1

You would need an array of 2 doubles for this purpose.

You can determine what values with this code:

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

int main(void) {
    char msg[sizeof(double) * 2] = "Hello World";
    double d[2];

    memcpy(d, msg, sizeof(d));
    printf("double test[2] = { %.20lg, %.20lg };\n", d[0], d[1]);
    return 0;
}

Executing it on my laptop produces:

double test[2] = { 2.1914441197069634153e+228, 3.2516248670450380385e-317 };
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 2
    This may produce a trap representation, invoking UB – nalzok Feb 28 '16 at 02:38
  • @sunqingyao - give an example. – Bob Jarvis - Слава Україні Feb 28 '16 at 02:42
  • @sunqingyao: The standard says it is possible if `double` has trap representations. Luckily, running this code on x86 hardware does not generate any such oddity, but 2 precisely defined IEEE double values. The OP's code does print `Hello World` on my laptop, which proves nothing, but fits the OP's purpose. – chqrlie Feb 28 '16 at 02:42
  • @BobJarvis By saying **may**, I mean the program will crash on some implementations, for example, those don't have \_\_STDC_IEC_559\_\_ defined – nalzok Feb 28 '16 at 02:51
  • The fact of initialising one member of a `union` (`msg` in this case) and accessing the value via another member of incompatible type (the array `d`) produces undefined behaviour. Producing a trap representation is one possible outcome of that (after all, the floating point representation is implementation defined - using IEEE format is not mandatory). There is no solution to this question that does not involve undefined behaviour. – Peter Feb 28 '16 at 02:52
  • However, I don't think this question can have an UB-free answer, because representations are not specified in C. So +1 – nalzok Feb 28 '16 at 02:59
  • @Peter: OK. There is no portable solution and UB may be invoked on some architectures. I updated my code to remove the `union` issue. – chqrlie Feb 28 '16 at 02:59
  • @Peter type punning via union is not UB in newer C standards, although you're right that the result may be a trap representation that would invoke UB if used. http://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified . But all this talk of UB is beside the point -- the question is about playing and hacking around, not writing portable, clean code. – Paul Hankin Feb 28 '16 at 03:04
  • The infamous unspecified values on union accessed via 2 different types is among the worst problems in the C Standard. It caused countless bugs in programs that relied on previous rather intuitive behavior that was broken by vicious compilers taking advantage of UB beyond reason. – chqrlie Feb 28 '16 at 03:06
  • @Paul Hankin : the standards have made some behaviours related to type punning more predictable. They haven't made the result (such as storing a union member as one member, retrieving it via another member of different type) well defined - the net behaviour is still undefined. The question includes no context, such as what compiler, what optimisation settings, how basic types are assumed to be represented - and is simply tagged as C. So the discussion of undefined behaviour is relevant. And saying the question is about "playing and hacking around" is irrelevant. – Peter Feb 28 '16 at 03:44
  • @Peter In C99+errata and later, writing one member of a union and reading another is *not* undefined. The result is an *unspecified value*, which is a different and much less troublesome concept. In particular the compiler is *not* allowed to assume that you do not do this. (The result *could* be a trap representation - in this case, in particular, it could be a signaling NaN - but this only provokes "runtime-undefined" behavior and only if it actually happens. The code generation will be as one expects.) – zwol Feb 28 '16 at 15:38