1

I have a function that is called by

myStruct *structName = myFunction(0);

The function looks like

myStruct *myfunction(int x)
{

    if ( x == NULL)
    {
        return NULL;
    }

/*rest of code*/
}

Passing NULL or 0 BOTH trigger the if (x== NULL) statement and I can't figure out why. I need to return from the function on NULL but continue if the value is 0. Any change made can only be made within the function itself.

9
  • 15
    NULL is 0.
    – tkausl
    Commented Jun 10, 2016 at 0:51
  • 5
    NULL should be used with pointers, not integers. There is no way that int x can be NULL, it is a value type. You might try C# or Java, they're easier to start with than C as they give better error messages, and check for more error conditions.
    – Erik Eidt
    Commented Jun 10, 2016 at 1:31
  • It sounds like you are trying to do an assignment. What you are trying to do cannot be done (since NULL and 0 are the same thing). Chances are you are reading the assignment incorrectly. Commented Jun 10, 2016 at 3:27
  • 1
    I'm voting to close this question as off-topic because it is more appropriate to ask at Stack Overflow. However, it would be closed as a duplicate of What is the difference between NULL, '\0' and 0.
    – user22815
    Commented Jun 16, 2016 at 23:28
  • 1
    @tkausl In C, the macro NULL is not specified to be 0. Having NULL defined as 0 is one of a number of possibilities and it is certainly common that way. Commented Jun 18, 2016 at 19:19

3 Answers 3

12

In C, NULL is a macro that expands either to 0 or (void*)0 (or something that has a similar effect).

In the first case, you can not differentiate between NULL and 0, because they are literally the same.
In the second case, your code will cause a compile error, because you can't compare an integer variable with a pointer.

3
  • "... NULL is a macro that expands either to 0 or ..." and " code will cause a compile error, because you can't compare an integer variable with a pointer" are contradictory. If NULL expands to 0, that is an int and certainty code if (NULL == ptr) is not an error. Even gcc generates a diagnostic, not an error, with a non-zero compare if (42 == ptr) Commented Jun 19, 2016 at 15:21
  • @chux: They are not contradictory because 0 is not an integer variable, but an integer constant (and a null-pointer constant as well). Besides, the reference to a compile error was for when NULL expands to (void*)0. Commented Jun 19, 2016 at 20:25
  • This is not true, NULL must compare equal to (void*)0, but it can take any value. if (x) checks that x is non-null, but (uintptr_t)NULL does not have to be 0.
    – yyny
    Commented Jul 31, 2020 at 15:08
4

First some background ...


The macros are NULL which expands to an implementation-defined null pointer constant; C11 §7.19 3

NULL typically is an integer constant 0 or (void*)0 or the like. It may have a different implementation or type - It could be ((int*) 0xDEADBEEF) as strange as that may be.

NULL might be type int. It might be type void * or something else. The type of NULL is not defined.


When the null pointer constant NULL is cast to any pointer, is is a null pointer. An integer 0 cast to a pointer is also a null pointer. A system could have many different (bit-wise) null pointers. They all compare equally to each other. They all compare unequally to any valid object/function. Recall this compare is done as pointers, not integers.

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function. C11 §6.3.2.3 3

int x;
if (&x == NULL) ... // this is false

So after all that chapter and verse how to distinguish NULL from 0?

If the macro NULL is defined as an int 0 - it is game over - there is no difference between 0 and NULL.

If NULL is not an int, then code can use _Generic() to differentiate NULL and 0. This does not help OP's "Any change made can only be made within the function itself." requirement as that function accepts an int augment.

If NULL is an int that has a different bit-pattern than 0, then a simple memcmp() can differentiate.

I suspect the whole reason for this exercise is to realize there is no portable method to distinguish NULL from 0.

2

Chapter and verse:

6.3.2.3 Pointers
...
3     An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
66) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19

In short, any 0-valued expression that appears in a pointer context is interpreted as NULL.

2
  • What is the significance of the term "constant" in "integer constant expression"? Does that mean if you had an integer variable x whose value was zero, that x == NULL is not guaranteed to be true? (Not that I think such an expression would be well-advised, even if it does work.) Commented Feb 13, 2021 at 20:36
  • @DominickPastore: A constant expression is something that can be evaluated at compile time - either a literal, an expression involving only literals, or a macro that expands to a literal or an expression involving only literals. NULL expands to (0) or ((void *) 0). I actually misspoke above when I said "any 0-valued expression" - a runtime 0 is not necessarily the same as a runtime null pointer value. I've never worked on a platform where runtime 0 wasn't also a null pointer value, but my experience isn't that broad, either.
    – John Bode
    Commented Feb 18, 2021 at 17:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.