-2
//static int initialized;
void print(struct student *arg) {
  #ifndef first_call
  #define first_call 1
  //if (!initialized) {
    //initialized = 1;
    printf("sizeof(*arg1): %lu\n", sizeof(*arg));
  //}
  #endif
  ...
}

I want to execute lines of code within if block only once.

Of course I know how to do that through different way(commented part).

But I want to know why my code doesn't work as I intended.

Thanks.

  • 1
    you cannot do that using preprocessor directives! – Jean-François Fabre Oct 13 '17 at 15:21
  • 3
    `#ifndef` etc...are pre-processor directives so only happen during compilation, not execution. – Chris Turner Oct 13 '17 at 15:21
  • You don't want to use condifional compilation for this. Use a simple `if` statement and a global or static variable. – Jabberwocky Oct 13 '17 at 15:21
  • #ifdef and #ifndef are preprocessor instructions, that are not evaluated when you run the program, but before compilation. – Pac0 Oct 13 '17 at 15:21
  • thanks for answers. but I saw similar codes at http://en.cppreference.com/w/c/preprocessor/conditional – Joonhee Jeong Oct 13 '17 at 15:22
  • What's wrong with your initial approach using `if (!initialized)` which is almost correct? `initialized` just needs to be static or global. – Jabberwocky Oct 13 '17 at 15:22
  • The code you've seen [here](http://en.cppreference.com/w/c/preprocessor/conditional) is not similar at all. Read the chapter dealing with the preprocessor and `#if/#else/#endif` in your C textbook – Jabberwocky Oct 13 '17 at 15:24
  • Like we said, the codes you found on cppreference aren't wrong, you are just not understanding the concept of preprocessor directives. Take a look at my answer. – Burstful Oct 13 '17 at 15:32

2 Answers2

3

A preprocessor directive will happen during compilation. Meaning, before your program will run it will take:

//static int initialized;
void print(struct student *arg) {
  #ifndef first_call
  #define first_call 1
  //if (!initialized) {
    //initialized = 1;
    printf("sizeof(*arg1): %lu\n", sizeof(*arg));
  //}
  #endif
  ...
}

And turn it into:

//static int initialized;
void print(struct student *arg) {
  #define first_call 1
  //if (!initialized) {
    //initialized = 1;
    printf("sizeof(*arg1): %lu\n", sizeof(*arg));
  //}
  ...
}

Which means, what you intended is not going to happen. You simply defined first_call as 1.

A temporary variable like initialized would be a good solution to make it run once. Do remember though, local variables are destroyed after you exit this function call.. Hint: Look up static variables..

This would work:

void print(struct student *arg) 
{
    static bool initialized = false;
    if (!initialized) 
    {
        initialized = true;
        printf("sizeof(*arg1): %lu\n", sizeof(*arg));
    }

    ...
}
Burstful
  • 347
  • 1
  • 10
  • Oh thank you Lakey. You say that preproccessor execute one time, before compile, so #ifndef ... #endif turn into just #define. right? – Joonhee Jeong Oct 13 '17 at 15:49
  • but I think that cppreference is also right. there are just many #ifdef. – Joonhee Jeong Oct 13 '17 at 15:52
  • Before compilation, these directives are dealt with. Meaning... it checks the conditions like #ifndef or #ifdef and " if not defined " it does what you say to do, and ends that "what to do" at the #endif. BEFORE COMPILATION. After preprocessor directives are dealt with, the code is compiled. – Burstful Oct 13 '17 at 15:52
  • Lol, I said cppreference is right. They are explaining how directives work, as i am. But your question was if you can use a #ifndef to make code run only once, and the answer is no. – Burstful Oct 13 '17 at 15:52
  • thank you for your additional explanation. I confused your meaning for my short English. Have a good day! – Joonhee Jeong Oct 13 '17 at 15:58
  • No problem! Any more questions let me know. – Burstful Oct 13 '17 at 16:00
0

You are going the wrong way. #ifdef's are preprocessor commands, that are parsed before compiler. This means everything placed within #ifdef block is simply removed before compilation if the condition is not satisfied.

For your particular problem one of the common approaches it to use a static variable:

int my_func()
{
    static int initialized = 0;

    if (!initialized)
    {
        /* Initialize */
        ...

        initialized = 1;
    }

    ...
}
Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95