1

I'm trying to write a code to check with a pointer of int if a number is even or not.
My code is like that:

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

void isEven (int *isFlag, int num) {
    if (num % 2 == 0) {
        *isFlag = 1;
    } else {
        *isFlag = 0;
    }
}

int main() {
    int num = 4;
    int *isFlag = 0;
    isEven(isFlag, num);
    printf("%d", isFlag);
}  

But I get segmentation fault and I'm expected to see that isFlag = 1, what is the problem in the code? (I know we can do it better but I'm trying to understand pointers)

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Pedro Gómez
  • 214
  • 1
  • 8
  • 1
    `int *isFlag = 0` is your problem. You should allocate memory for an int and assign it to isFlag. – Tarik Mar 26 '21 at 18:51
  • 1
    Turn on compiler warnings and read them. `printf("%d", isFlag);` -> `printf("%d", *isFlag);`. That's one of the problems. – klutt Mar 26 '21 at 18:51
  • `printf("%d", isFlag)` prints the address of the pointer. – Tarik Mar 26 '21 at 18:53
  • You use a pointer to write. Tell me where that pointer is pointing to when you write via it and I don't have to tell you why there is a segfault. – Yunnosch Mar 26 '21 at 18:54
  • was about to post my answer and then I saw 4 answers, seems like everyone is jumping on the bandwagon ^^ Note that you are declaring isFlag as a ptr, I think dbush's answer reflects the most accurately what you should be doing, along with the other nice explanations – Antonin GAVREL Mar 26 '21 at 19:04
  • @Tarik Most likely but not necessarily. It's UB – klutt Mar 26 '21 at 19:07
  • @klutt Thanks for your correction. How can we find out when something is UB. Any reference I can turn to? Is there a format string to print the address of a pointer? – Tarik Mar 26 '21 at 20:33
  • @Tarik To find out what's UB in general, read the C standard http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf To find the right format string, read the documentation for `printf`. http://www.cplusplus.com/reference/cstdio/printf/ Some cases of UB can also be found in such documentation – klutt Mar 26 '21 at 21:04

5 Answers5

3

int *isFlag = 0; defines isFlag to be a pointer to int and initializes it to point to “nowhere.” (When the constant 0 is used for a pointer, it means a null pointer, which does not point to any object or function.)

You do not need to create a pointer in your main routine for this function. You can define an ordinary int with int isFlag = 0; and pass the address of the int to isEven with isEven(&isFlag, num);.

&isFlag will take the address of isFlag and pass it to isEven. The isEven parameter int *isFlag will have the value of that pointer. Even though it has the same name as the isFlag in main, it is a different object, because it is defined in a different scope (inside the function parameter instead of inside main), and it has a different type; it will be a pointer to an int. So you use it as *isFlag inside isEven to access the int that it points to.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
2

You're declaring isFlag as a pointer in main and setting it to a NULL pointer constant. You then pass that NULL pointer to isEven which attempts to dereference it. Dereferencing a NULL pointer triggers undefined behavior which in the case causes a crash.

Define isFlag as an int and pass its address to isEven.

int main() {
    int num = 4;
    int isFlag;
    isEven(&isFlag, num);
    printf("%d", isFlag);
}  
dbush
  • 205,898
  • 23
  • 218
  • 273
1

what is the problem in the code?

Let your compiler tell you what problems it thinks your code may have, before asking us:

Why should I always enable compiler warnings?

If you did that, the compiler would tell you (using gcc as an example):

<source>: In function 'main':
<source>:16:14: warning: format '%d' expects argument of type 'int', but argument 2 has
type 'int *' [-Wformat=]
   16 |     printf("%d", isFlag);
      |             ~^   ~~~~~~
      |              |   |
      |              int int *
      |             %ls

that's not exactly why you're getting the segmentation fault, but it does tell you you're treating a pointer-to-an-int as though it was an int. That's true for the printf() instruction - but it's true more generally. So, your initialization to 0 is how you would initialize an int... as other answers explain, that's not what you want to be doing.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
1

The problem of your code is that it seems you made a typo because you do not have yet solid knowledge relative to pointers.

In this declaration

int *isFlag = 0;

you declared a null pointer because it is initialized by integer constant 0. So accessing memory using a null pointer results in undefined behavior.

On the other hand, in this statement

printf("%d", isFlag);

you are outputting the variable isFlag as a variable of the type int.

What you need is to declare the variable as indeed having the type int and pass it to the function by reference through a pointer to it.

That is the code in main will look like

int main( void ) {
    int num = 4;
    int isFlag = 0;
    isEven( &isFlag, num );
    printf("%d", isFlag);
}  

Also the function isEven could be defined simpler

void isEven( int *isFlag, int num ) {
    *isFlag = num % 2 == 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

There are several problems that everyone has summed up.

If you still want to stick to your example (you shouldn't, prefer dbush's solution), you can still achieve it the following way, by allocating memory to the ptr:

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

void isEven (int *isFlag, int num) {
    if (num % 2 == 0) {
        *isFlag = 1;
    } else {
        *isFlag = 0;
    }
}
int main() {
    int num = 4;
    int *isFlag;

    isFlag = malloc(sizeof(int));
    isEven(isFlag, num);
    printf("%d\n", *isFlag); // also use *isFlag to print the value at ptr's address
    printf("%p\n", isFlag); // print isFlag's address
}  
Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81