Search code examples
cstdoutstdinstderr

A complicated syntax over preprocessor in C


I am trying to figure out code in C and I am stuck at trying to understand what the part of preprocessor actually does. The part of code I do not understand is following:

#define ERR(source) (perror(source),\
         fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
         exit(EXIT_FAILURE))

whole code is very short, and looks as follows:

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

#define ERR(source) (perror(source),\
             fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
             exit(EXIT_FAILURE))

int main(int argc, char** argv) {
    char name[22];
    scanf("%21s",name);
    if(strlen(name)>20) ERR("Name too long");
    printf("Hello %s\n",name);
    return EXIT_SUCCESS;
}

Solution

  • The backslash in the macro means you can read the next line as if it is one line, so it boils down to this:

     #define ERR(source) (perror(source), fprintf(stderr,"s:%d\n",__FILE__,__LINE__), exit(EXIT_FAILURE))
    

    A #define preprocessor statement is used to replace code with other code, for example

    #define SOMECONSTANT 5
    

    will replace SOMECONSTANT in your code with 5, before compiling the code. The preprocessor also understands function-like syntax, which is what you have here.

    Your macro results in the following main body:

    int main(int argc, char** argv) {
        char name[22];
        scanf("%21s",name);
        if(strlen(name)>20) (perror("Name too long"), fprintf(stderr,"s:%d\n",__FILE__,__LINE__), exit(EXIT_FAILURE));
        printf("Hello %s\n",name);
        return EXIT_SUCCESS;
    }
    

    The macro in your case uses the comma-operator to put a few statements together, so you can use it as one statement. Usually, your code would be written as:

    int main(int argc, char** argv) {
        char name[22];
        scanf("%21s",name);
        if(strlen(name)>20) {
              perror("Name too long");
              fprintf(stderr,"s:%d\n",__FILE__,__LINE__);
              exit(EXIT_FAILURE);
        }
        printf("Hello %s\n",name);
        return EXIT_SUCCESS;
    }
    

    Hopefully you understand what is going on now.