Home > Enterprise >  C vs C Macro string concatenation difference
C vs C Macro string concatenation difference

Time:01-10

I try to write a macro like following: taken from link and I apply same rule to my software whit out success. I notice some difference from C and C , but I don't understand why, the macro are preprocessor job ! also I notice some difference passing to the macro the values coming from an enumerators.

#include <stdio.h>
#define CONCAT(string) "start"string"end"
int main(void) 
{
    printf(CONCAT("-hello-"));
    return 0;
}

the reported link used to try online the code link to a demo on ideone allow selection of different language C is ok but changing to C it doesn't work. Also in my IDE Visual Studio Code (MinGw C ) doesn't work.

My final target is write a macro to parametrize printf() function, for Virtual Console application using some escape codes. I try to add # to the macro concatenation and seems work but in case I pass an enumerator to the macro I have unexpected result. the code is :

#include <stdio.h>
#define def_BLACK_TXT 30
#define def_Light_green_bck 102

#define CSI "\e["
#define concat_csi(a, b) CSI #a ";" #b "m"
#define setTextAndBackgColor(tc, bc) printf(concat_csi(bc, tc))

enum VtColors { RESET_COLOR = 0, BLACK_TXT = 30, Light_green_bck = 102 };

int main(void){
    setTextAndBackgColor(30, 102);
    printf("\r\n");
    setTextAndBackgColor(def_BLACK_TXT , def_Light_green_bck );
    printf("\r\n");
    setTextAndBackgColor(VtColors::BLACK_TXT , VtColors::Light_green_bck );
    printf("\r\n");
    printf("\e[102;30m");//  <<---   this is the expected result of macro expansion
}

//and the output is : ( in the line 3 seems preprocessor don't resolve enum (the others line are ok) )
[102;30m 
[102;30m 
[VtColors::Light_green_bck;VtColors::BLACK_TXTm
[102;30m

Obviously I want use enumerators as parameter... (or I will change to #define).

But I'm curious to understand why it happens, and why there is difference in preprocessor changing from C to C .

If anyone know the solution, many thanks.

CodePudding user response:

There appears to be some compiler disagreement here.

MSVC compiles it as C without any issues.

gcc produces a compilation error.

The compilation error references a C feature called "user-defined literals", where the syntax "something"suffix gets parsed as a user-defined literal (presuming that this user-defined literal gets properly declared).

Since the preprocessor phase should be happening before the compilation phase, I conclude that the compilation error is a compiler bug.

Note that adding some whitespace produces the same result whether it gets compiled as C or C (and makes gcc happy):

#define CONCAT(string) "start" string "end"

EDIT: as of C 11, user-defined literals are considered to be distinct tokens:

Phase 3

  1. The source file is decomposed into comments, sequences of whitespace characters (space, horizontal tab, new-line, vertical tab, and form-feed), and preprocessing tokens, which are the following:

a) header names such as or "myfile.h"

b) identifiers

c) preprocessing numbers d) character and string literals , including user-defined (since C 11)

emphasis mine.

This occurs before phase 4: preprocessor execution, so a compilation error here is the correct result. "start"string, with no intervening whitespace, gets parsed as a user-defined literal, before the preprocessor phase.

CodePudding user response:

to summarize the behavioral is the following: (see comment in the code)

#include <stdio.h>
#define CONCAT_1(string) "start"#string"end"
#define CONCAT_2(string) "start"string"end"
#define CONCAT_3(string) "start" string "end"
int main(void) 
{
    printf(CONCAT_1("-hello-"));      // wrong insert double quote
    printf("\r\n");
    printf(CONCAT_1(-hello-));        // OK but is without quote
    printf("\r\n");
#if false
    printf(CONCAT_2("-hello-"));   // compiler error
    printf("\r\n");
#endif
    printf(CONCAT_3("-hello-"));     // OK
    printf("\r\n");
    printf("start" "-hello-" "end");    // OK
    printf("\r\n");
    printf("start""-hello-""end");      // OK
    printf("\r\n");
    return 0;
}
output:
start"-hello-"end   <<<--- wrong insert double quote
start-hello-end
start-hello-end
start-hello-end
start-hello-end
  • Related