Why/how does this compile?

c++, visual-studio

Solution

C++ has a special loophole for string literals for compatibility with pre-`const` C-style code. Although string literals are arrays of `const char`, they can be converted to a pointer to non-`const` char.

Paraphrasing 4.2/2 [conv.array]: a 'narrow' string literal can be converted to an rvalue of type pointer to non-`const` `char`. The conversion is only considered when there is an explicit target type (e.g. a function parameter) and not when a general lvalue to rvalue conversion is required.

This conversion is deprecated, but still available. Note that while the conversion allows the literal to be converted to a pointer to non-`const char` type, it would still invoke undefined behaviour to try to modify any of the characters in the string literal through this pointer.

Problem

C++ in MS Visual Studio 2008. Warning level 4 plus a load of extra warnings enabled as well. I'd expect this to give a warning at least, but more likely a compiler error? Function declaration is as follows: ``` int printfLikeFunction( const int bufferLength, char * const buffer, const char * const format, ... ); ``` Code usage - there's a typo: although the ARRAY_SIZE of outputBuffer is passed in, outputBuffer itself isn't - surely this should not compile: ``` printfLikeFunction( ARRAY_SIZE( outputBuffer ), "Format: %s, %s", arg1, arg2 ); ``` Clearly this is wrong and a mistake has been made. However the compiler should have caught it! The buffer parameter should be a char-pointer, and it's being passed a string literal which is a const char-pointer. This must be an error. (arg1 and arg2 are (possibly const) char pointers as well, so coincidentally the declaration is matched even without outputBuffer being in the correct place). At run time, this code crashes as it attempts to write into the string literal. No surprise there, I just don't understand how it was allowed to compile. (Though, incidentally, this is presumably why sprintf_s has the buffer and size parameters in a different order to this function - it makes such errors unequivocally fail).

Original source