Why / how does it compile?

C ++ in MS Visual Studio 2008. Warning level 4 plus the addition of additional warnings. I expect this to give a warning at least , but most likely a compiler error?

The function declaration is as follows:

int printfLikeFunction( const int bufferLength, char * const buffer, const char * const format, ... ); 

Using the code is a typo: although ARRAY_SIZE outputBuffer is passed, outputBuffer itself - this should not be compiled:

 printfLikeFunction( ARRAY_SIZE( outputBuffer ), "Format: %s, %s", arg1, arg2 ); 

Clearly, this is wrong and a mistake has been made. However, the compiler had to catch it! The buffer parameter must be char -pointer, and it receives a string literal, which is const char -pointer. It must be a mistake. (arg1 and arg2 are also (possibly const) char pointers, so the declaration match is consistent even though outputBuffer is in the right place).

At runtime, this code crashes when it tries to write to a string literal. Not surprisingly, I just don't understand how it is allowed to compile.

(Although, by the way, apparently, this is due to the fact that sprintf_s has buffer and size parameters in a different order for this function - it makes such errors uniquely unsuccessful).

+5
c ++ visual-studio
Oct 07 '09 at 8:44
source share
4 answers

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

To paraphrase 4.2 / 2 [conv.array]: a "narrow" string literal can be converted to an rvalue of a type pointer to const char . A conversion is only taken into account when an explicit target type exists (for example, a function parameter), and not when a conversion of the general lvalue to rvalue is required.

This conversion is outdated, but still available. Please note: although the conversion allows you to convert a literal to a pointer to a non- const char type, it will still refer to undefined behavior to try to change any of the characters in the string literal through this pointer.

+9
Oct 07 '09 at 9:18
source share

I seem to remember that the compiler has an option that controls the processing of string literals. By default, they are treated as char * so as not to break all existing non-constant code, but you can change it to treat them as const char * . This may help cause the error you are looking for.

(later) I don’t have a Microsoft compiler right now, but looking at the MSDN link, I cannot find such an option. Perhaps I am thinking of a GCC that has this option.

+2
07 Oct '09 at 8:47
source share

int printfLikeFunction (const int bufferLength, char * constant buffer, const char * const, ...);

The buffer parameter is set as char * const, so it protects only the address of the buffer that should be changed, and not the contents of the buffer.

to avoid writing a buffer, you need to declare it as const char * const as a format.

the compiler allows you to write to the buffer, since you declare it as char *. The post postfix const modifier prevents reassigning the buffer value in your function.

see http://jriddell.org/const-in-cpp.html to see the effect of the const modifier on variables

+1
Oct 07 '09 at 9:01
source share

String literals in C are const char ( char*const ) pointers, not constant pointers to constant characters ( const char* const ).

C ++ initially followed the use of C, but then at some point in ANSI, C ++ was modified (I'm not sure when) to make them const char* const . Microsoft products have traditionally tended to evaluate backward compatibility with previous versions compared to compliance - there may be a compiler option to force β€œnew” behavior, but since the string literal examples on MSDN are not constants, I doubt it is.

+1
07 Oct '09 at 9:05
source share



All Articles