Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ways a program might detect whether NULL is defined with integer or pointer type?

C allows NULL to be defined to any null pointer constant, in other words, any integer constant expression that evaluates to 0, or such an expression cast to void *. My question concerns whether the choice of definition really matters, i.e. whether an otherwise-correct program might depend on which definition is used. For the purpose of this question, I'd like to ignore issues like NULL being passed to variadic functions or functions lacking prototypes, since I've already dealt with it separately. Let's assume sizeof NULL == sizeof(void *) and sizeof NULL == sizeof(T) for some integer type T, so that sizeof is not sufficient to answer the question of whether NULL has pointer type.

Obviously, C11 provides a way to distinguish the type of NULL or any other expression: the _Generic keyword.

C99 also provides one obscure way that seems to be reliable:

int null_has_ptr_type()
{
    char s[1][1+(int)NULL];
    int i = 0;
    return sizeof s[i++], i;
}

Are there any other methods by which the type of NULL may be determined by a conforming C program? Any that work in C89?

like image 240
R.. GitHub STOP HELPING ICE Avatar asked Jan 09 '13 15:01

R.. GitHub STOP HELPING ICE


People also ask

Is NULL integer or pointer?

NULL itself is not a pointer, it is a macro that can be used to initialize a pointer to the null pointer value of its type. When compared to a pointer, it compares equal if the pointer is a null pointer and unequal if the pointer is a valid pointer to an object of its type.

How to pass a null pointer to a function in C?

b) To pass a null pointer to a function argument when we don't want to pass any valid memory address. c) To check for null pointer before accessing any pointer variable. So that, we can perform error handling in pointer related code e.g. dereference pointer variable only if it's not NULL.

How to check if a pointer is a null pointer in C?

If any pointer is being compared to 0, then this is a check to see if the pointer is a null pointer. This 0 is then referred to as a null pointer constant. The C standard defines that 0 is typecast to (void *) is both a null pointer and a null pointer constant. The macro NULL is provided in the header file “stddef.h”.

What is null in C programming?

At the very high level, we can think of NULL as a null pointer which is used in C for various purposes. Some of the most common use cases for NULL are a) To initialize a pointer variable when that pointer variable isn’t assigned any valid memory address yet. b) To check for a null pointer before accessing any pointer variable.

Is the expression (int*) 0 a null pointer constant?

Evaluating the expression (int*)0yields a null pointer of type int*. (int*)0is not a null pointer constant. A null pointer constantis a particular kind of expression that may appear in C source code. A null pointeris a value that may occur in a running program.

What is a NullPointerException?

NullPointerException is a RuntimeException. In Java, a special null value can be assigned to an object reference. NullPointerException is thrown when program attempts to use an object reference that has the null value.


Video Answer


3 Answers

Through the question, answers, and comments, I think we established:

  1. The C11 way is easy (_Generic).
  2. The C99 way is fairly unreliable due to buggy compilers.
  3. Stringifying approaches are a dead-end due to typedef.
  4. No other approaches were found.

So the answer seems to be that there's no reliable pre-C11 method, and seemingly no valid pre-C99 method.

like image 155
R.. GitHub STOP HELPING ICE Avatar answered Oct 23 '22 07:10

R.. GitHub STOP HELPING ICE


Get the string definition of NULL and then do an as complete check as you want. Here is a very simple minded one:

#define XSTR(x) #x
#define STR(x) XSTR(x)

if (STR(NULL)[0] == '(') {
   ...
}

But I don't know how you'll handle a __null which can come out from that.

like image 44
AProgrammer Avatar answered Oct 23 '22 08:10

AProgrammer


Couldn't you stringify the macro and look at the string?

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

# define STRINGIFY(x) STRINGIFY_AUX(x)
# define STRINGIFY_AUX(x) #x

int main(void)
{
  const char *NULL_MACRO = STRINGIFY(NULL);

  if (strstr("void", NULL_MACRO) != NULL)
    puts("pointer");
  else
    puts("integer");
}

It correctly prints "integer" if you add this (usually NULL has pinter type):

# undef NULL
# define NULL 0

NULL cannot be something like (int) ((void *) 0) because the standards doesn't state that a null pointer constant converted to an integer type is still a null pointer constant.

Furthermore, the standard also say this about integer constant expressions (C11, 6.6/6):

An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.

EDIT: actually this doesn't work with things like:

# define NULL (sizeof(void *) - sizeof(void *))

(thanks for noticing) and this cannot be checked in a trivial way as the OP needs, a little bit of work (simple parsing) is required.

EDIT 2: and there are also typedef as comment correctly pointed out.

like image 24
effeffe Avatar answered Oct 23 '22 07:10

effeffe