What happens when you type cast an integer value into a char pointer?
In general, that is undefined behavior (at least as soon as you dereference it). Be very scared. Read a lot more about UB (it is a tricky subject).
In some documented cases, you can case an uintptr_t
or intptr_t
integral value into a valid pointer.
In your case, your heap allocated string is too short (so you have a buffer overflow, which is one of the many examples of UB). You forgot the space for the terminating NUL byte, and you forgot to check against failure of malloc
. BTW, sizeof(char)
is always 1.
You could code:
if (userInput < 0 || userInput > 99)
return NULL;
char *myString = (char *)malloc(3);
if (!myString) { perror("malloc myString"); exit(EXIT_FAILURE); };
myString[0] = (int)floor(userInput/10.0) + '0';
myString[1] = userInput%10 + '0';
myString[2] = (char)0;
return myString;
On most systems (but not all), (char*)-1
is never a valid address (always outside of the virtual address space) and can never be given by system (or standard) functions. On My Linux/x86-64 desktop, I know that (char*)-1
is not a valid address (e.g. because it is MAP_FAILED
), and I could (sometimes) use that as a sentinel non-null pointer value (which should not be derefenced). But that makes my code less portable.
So you could decide and document that your integerToString
gives (char*)-1
on non-integer input and NULL
on heap allocation failure. That would work on my Linux/x86-64 desktop (so I sometimes do that). But that is not pure (portable) C11 code.
But if you stick to the C11 standard (read n1570) it is implementation defined what and if (char*)-1
is meaningful. It might be some trap representation that you are not even allowed to compare (even if I don't know any actual C implementation doing that).
Actually your example illustrates that people never code for pure standard C11; they always (and so do I) make additional assumptions on the C implementation; but you do need to be aware of them, and these assumptions could make the porting of your code to some hypothetical future machine a nightmare.
Will this program always work?
This is a too general question. Your original program didn't even handle failure of malloc
and had a buffer overflow (because you forgot the space for the terminating zero byte). However, sadly for you, it would apparently often seems to work (and that is why UB is so scary). Consider however this (standard conforming, but non-realistic) malloc
implementation as food for thought.
(explaining exactly why your program appears to behave like you want is really difficult, because you need to dive into several implementation details)