if( mystruct == NULL )

mystruct is not a pointer, so you cannot compare it with NULL.

You have three options:

  1. Add a status field to MyStruct to indicate whether the struct has been initialized correctly.
  2. Allocate the struct on the heap and return it by pointer.
  3. Pass the structure as a pointer argument and return a status code (thanks @Potatoswatter).
Answer from NPE on Stack Overflow
🌐
Quora
quora.com › Is-it-legal-in-C-C-to-return-NULL
Is it legal in C/C++ to 'return NULL'? - Quora
Answer (1 of 20): There is no such thing like “C/C++”. return NULL is legal in C and it usually means, by convention, that something went wrong, e.g. an allocation, and the calling context is supposed to handle the error. In C++, while return nullptr would be legal and well-defined too, ...
🌐
Reddit
reddit.com › r/c_programming › difference between return 1 and return null
r/C_Programming on Reddit: Difference between return 1 and return NULL
October 15, 2023 -

Source: https://cs50.harvard.edu/x/2023/labs/5/

Here is the portion that I need help with:

// Create a new individual with `generations`
person *create_family(int generations)
{
    // TODO: Allocate memory for new person
    person *new_person = malloc(sizeof(person));
    if (new_person == NULL)
    {
        return 1;
    }

Here is what ChatGPT says on my return 1 usage:

The TODO comment indicates that you need to allocate memory for a new person structure. In the provided code, you're using malloc(sizeof(person))to allocate memory dynamically. However, when memory allocation fails (i.e., malloc returns NULL), you're returning the integer 1 from the create_family function. Typically, a function returning a pointer should return NULL to indicate a failure.

Next, I rephrased the code:

// Create a new individual with `generations`
person *create_family(int generations)
{
    // TODO: Allocate memory for new person
    person *new_person = malloc(sizeof(person));
    if (!new_person)
    {
        return 1;
    }

ChatGPT reply:

Your updated code checks if new_person is NULL using the condition if (!new_person).

However, it's better to return NULL*(a pointer) in case of memory allocation failure, rather than the integer* 1.

Here's the modified code:

// Create a new individual with `generations`
person *create_family(int generations)
{
    // TODO: Allocate memory for new person
    person *new_person = malloc(sizeof(person));
    
    // Check if memory allocation was successful
    if (!new_person)
    {
        fprintf(stderr, "Memory allocation failed.\n");
        return NULL;
    }
    
    // Rest of the code for creating the family tree
    // ...

    return new_person;
}

In this modification:

  • If memory allocation fails, the function prints an error message to the standard error stream using fprintf(stderr, "Memory allocation failed.\n");

  • return NULL;
    is used to indicate that the function failed to create a new person due to a memory allocation failure.

  • If memory allocation is successful, the function proceeds with the rest of the code for creating the family tree.

Returning NULL in case of memory allocation failure is a common practice in C, as it allows the calling code to check for errors by examining the returned pointer.

Full project code provided by CS50:

// Simulate genetic inheritance of blood type

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Each person has two parents and two alleles
typedef struct person
{
    struct person *parents[2];
    char alleles[2];
} person;

const int GENERATIONS = 3;
const int INDENT_LENGTH = 4;

person *create_family(int generations);
void print_family(person *p, int generation);
void free_family(person *p);
char random_allele();

int main(void)
{
    // Seed random number generator
    srand(time(0));

    // Create a new family with three generations
    person *p = create_family(GENERATIONS);

    // Print family tree of blood types
    print_family(p, 0);

    // Free memory
    free_family(p);
}

// Create a new individual with `generations`
person *create_family(int generations)
{
    // TODO: Allocate memory for new person
    person *new_person = malloc(sizeof(person));
    if (new_person == NULL)
    {
        return 1;
    }

    // If there are still generations left to create
    if (generations > 1)
    {
        // Create two new parents for current person by recursively calling create_family
        person *parent0 = create_family(generations - 1);
        person *parent1 = create_family(generations - 1);

        // TODO: Set parent pointers for current person

        // TODO: Randomly assign current person's alleles based on the alleles of their parents
    }

    // If there are no generations left to create
    else
    {
        // TODO: Set parent pointers to NULL

        // TODO: Randomly assign alleles
    }

    // TODO: Return newly created person
    return NULL;
}

// Free `p` and all ancestors of `p`.
void free_family(person *p)
{
    // TODO: Handle base case

    // TODO: Free parents recursively

    // TODO: Free child
}

// Print each family member and their alleles.
void print_family(person *p, int generation)
{
    // Handle base case
    if (p == NULL)
    {
        return;
    }

    // Print indentation
    for (int i = 0; i < generation * INDENT_LENGTH; i++)
    {
        printf(" ");
    }

    // Print person
    if (generation == 0)
    {
        printf("Child (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]);
    }
    else if (generation == 1)
    {
        printf("Parent (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]);
    }
    else
    {
        for (int i = 0; i < generation - 2; i++)
        {
            printf("Great-");
        }
        printf("Grandparent (Generation %i): blood type %c%c\n", generation, p->alleles[0], p->alleles[1]);
    }

    // Print parents of current generation
    print_family(p->parents[0], generation + 1);
    print_family(p->parents[1], generation + 1);
}

// Randomly chooses a blood type allele.
char random_allele()
{
    int r = rand() % 3;
    if (r == 0)
    {
        return 'A';
    }
    else if (r == 1)
    {
        return 'B';
    }
    else
    {
        return 'O';
    }
}

🌐
Eskimo
eskimo.com › ~scs › cclass › notes › sx10d.html
10.4 Null Pointers
The most straightforward way to ``get'' a null pointer in your program is by using the predefined constant NULL, which is defined for you by several standard header files, including <stdio.h>, <stdlib.h>, and <string.h>. To initialize a pointer to a null pointer, you might use code like
🌐
Quora
quora.com › How-do-you-return-a-null-pointer-in-C
How to return a null pointer in C - Quora
Answer (1 of 7): “How do you return a null pointer in C?” This will do it: [code]return (void*)0; [/code]Enjoy your null pointer!
🌐
SEI CERT
wiki.sei.cmu.edu › confluence › display › c › MSC19-C.+For+functions+that+return+an+array,+prefer+returning+an+empty+array+over+a+null+value
MSC19-C. For functions that return an array, prefer returning an empty array over a null value - SEI CERT C Coding Standard - Confluence
The problem arises in this setup when no items are being stocked. getStock would recognize that length = 0 and would return NULL. In this noncompliant code example, erroneous behavior results from getStock returning NULL while main neglects to check for such a value.
🌐
GeeksforGeeks
geeksforgeeks.org › c language › null-pointer-in-c
NULL Pointer in C - GeeksforGeeks
We just have to assign the NULL value. Strictly speaking, NULL expands to an implementation-defined null pointer constant which is defined in many header files such as “stdio.h”, “stddef.h”, “stdlib.h” etc.
Published   January 10, 2025
Find elsewhere
Top answer
1 of 2
5

[H]ow do I return NULL from a integer result type function?

You don't. NULL is a macro representing a value of type void *. It is not an int, so a function returning int cannot return NULL.

Now, it is possible to convert NULL or any other pointer to type int, but the result of such a conversion is a valid, ordinary int. You seem to be looking instead for some kind of distinguished value, but there is none available unless you reserve such a value yourself. For example, you might reserve INT_MIN for that purpose. Of the built-in types, only pointer types afford general-purpose distinguished values (null pointers).

To provide for your function to signal failure to the caller, you have a couple of alternatives to reserving a value. The most common one is to use the function's return value only to report on the success or failure of the call, and to deliver any output -- in your case a node's value -- via a pointer argument:

int valueOf(t_node *node, int n, int *result) {
    int current = 0;

    while (current < n && node != NULL) {
        node = node->next;
        current += 1;
    }

    if (node == NULL) {
        // no such node -- return a failure code
        return 0;
    } else {
        // current == n
        *result = node->value;
        return 1;
    }
}
2 of 2
4

In C, NULL is just a synonym for 0. So you really only need to do this...

if (current > n) {
    return 0;
}

However, NULL usually refers to a pointer value that is undefined and not an integer. In C, integer values are not references as they are in many interpreted languages. They are scalar and can't be referred to implicitly with a pointer.

If you want to indicate an error condition or undefined behavior when current > n, you will have to provide a separate mechanism for indicating that the value isn't usable. Usually, C functions will return a -1 on an error. Since you are using the integer return for a value, that would mean that a valid value could never be -1.

It looks like you're handling a linked list and you want to limit the number of items to be checked. A possible way around this might be...

int valueOf(t_node *node, int n, int *val){
    int current = 0;
    int value;
    while (node -> next != NULL) {
        value = node -> val;
        if (current == n) {
            // This notation is for dereferencing a pointer.
            *val = value;
            return 0;
        }
        if (current > n) {
            return -1;
        }
        node = node -> next;
        current += 1;
    }
    // This method also gives you a way to indicate that
    // you came to the end of the list. Your code snippet
    // would have returned an undefined value if node->next == null
    return -1;
}
🌐
Bytes
bytes.com › home › forum › topic
how can I return nothing? - C / C++ - Bytes
There's `return NULL;', but that's not quite what you're after: even `NULL' is "something. " A C function either returns a value of a specified type, or never returns a value of any kind (such a function is written as if it "returned" a value of the type `void'). There are a few avenues open to you. One is to return either the prime number or some obvious non- prime like 0 or -1; this is sometimes called "in-band signaling."
🌐
The Coding Forums
thecodingforums.com › programming languages › c, c++ and c#
HELP:function at c returning (null) | C, C++ and C# | Coding Forums
November 13, 2023 - #include <stdio.h> #include <stdlib.h> /* * todo can be -> * 1 -> read * 2 -> wright * 3 -> overwright * WILL ADD MORE */ /* * mode can be -> * 0 -> none of the below * 1 -> read all lines * 2 -> read one line * WILL ADD MORE */ char *open_readF(char *filepath,const int mode,const int todo){ FILE *file = fopen(filepath,"r"); char result[100]; fgets(result, 100, file); return result; } int main(){ /* here is the code that works,its the same,but it works somehow */ FILE *file = fopen("addons.c","r"); char result[100]; fgets(result, 100, file); printf("CODE STRIPED FROM FUNCTION ->%s\n",result); char *var = open_readF("addons.c",0,1); printf("FUNCTION ->%s\n",var); return 0; }
Top answer
1 of 5
5

NULL is a pointer value - or rather a null-pointer value.

NULL means that the function can't find where your pointer should point to - for example if you want to open a file, but it doesn't work your file pointer is returned as NULL. So you can test the value of a pointer and check to see if it worked or not.

If you are writing a routine

int length()

then you could return a negative value if length is unable to read the length of whatever you send it - this would be a way of indicating an error, because normally lengths can never be negative....

2 of 5
3

It is a matter of convention and you should clearly have one in your head and document it (at least in comments).

Sometimes a pointer really should always point to a valid address (see this intSwap example, both arguments should be valid pointers). At other times, it should either be such a valid address, or be NULL. Conceptually the pointer type is then by convention a sum type (between genuine pointer addresses and the special NULL value).

Notice that the C language does not have a type (or a notation) which enforces that some given pointer is always valid and non-null. BTW, with GCC specifically, you can annotate a function with __attribute__ using nonnull to express that a given argument is never null.

A typical example is FILE* pointers in <stdio.h>. The fopen function is documented to be able to return NULL (on failure), or some valid pointer. But the fprintf function is expecting a valid pointer (and passing NULL to it as the first argument is some undefined behavior, often a segmentation fault; and UB is really bad).

Some non-portable programs even use several "special" pointer values (which should not be dereferenced), e.g. (on Linux/x86-64) #define SPECIAL_SLOT (void*)((intptr_t)-1) (which we know that on Linux it is never a valid address). Then we could have the convention that a pointer is a valid pointer to a valid memory zone, or NULL or SPECIAL_SLOT (hence, if seen as an abstract data type, it is a sum type of two distinct invalid pointers NULL and SPECIAL_SLOT and the set of valid addresses). Another example is MAP_FAILURE as result of mmap(2) on Linux.

BTW, when using pointers in C to heap allocated data (indirectly obtained with malloc), you also need conventions about who is in charge of releasing the data (by using free, often thru a supplied function to free a data and all its internal stuff).

Good C programming requires many explicit conventions regarding pointers, and it is essential to understand them precisely and document them well. Look for example[s] into GTK. Read also about restrict.

🌐
Reddit
reddit.com › r/cpp_questions › returning reference of null pointer
r/cpp_questions on Reddit: Returning reference of NULL pointer
July 18, 2021 -

In following function I'm trying find a node in Binary tree that matches the key. I'm passing reference node pointer as smart pointer and this function returns a refernce to node pointer.

How can I return NULL ? As the return value of function is std::unique_ptr<node>& so it is supposed to return a reference.

std::unique_ptr<node>& BST::ReturnNodePrivate(const int& key, std::unique_ptr<node> &ptr){
    if(NULL != ptr){
        if(ptr->key == key){
            return ptr;
         } 
    } 
     else{ 
        return NULL; 
     } 
}

How can I return NULL ?

🌐
Cprogramming
cboard.cprogramming.com › c-programming › 172944-define-struct-literally-returning-null-version.html
define struct literally for returning a null version
In a function which finds and returns the right element from the chars_data array, I’m trying to define and return a null version of the character_data structure for when what’s being asked for isn’t found.
Top answer
1 of 4
9

Returning NULL in case of success (the most simple case for success at that) is definitely contrary to what most people will expect.

Returning a pointer that the user has to manually destruct isn’t super great either. I’d suggest using C++11 unique_ptr but using C++11 may not be feasible in your case.

One thought I had is to make TestRoute private and have the Planner call it whenever it computes a new route.

If the test fails, return NULL, otherwise return the route.

What’s nice about this approach is that you can implement TestRoute however you (or your colleague) please, and the user of the class won’t need to know the details of how it is implemented. The user will just ask for a route from point A to point B and will be guaranteed it’s a valid route with refueling points so long as they don’t receive NULL.

You could also split your method into a few different methods if the performance hit isn’t too great.

For example, for TestRoute, have it return true if the route is possible, false if not.

bool TestRoute(const Route* r)

Have another method TestRouteNeedRefuel that returns true if the route will require refueling, false if not

bool TestRouteNeedRefuel(const Route* r)

Then have a final method, GenerateRefuelRoute that returns a new route with the proper refuel points

Route* TestRoute(const Route* r)
//use this if at all possible
std::unique_ptr<Route> TestRoute(const Route* r)

As far as performance goes, remember to profile before making assumptions. If your colleague is worried about copying Route more than needed (and he may have good reason to, as we don't know how expensive it is or what the target platform is) then clearly performance is an important requirement. I would suggest first implementing as clean an interface as can be done, profiling to find where the bottlenecks REALLY are, and then implementing a few speed hacks where necessary.

2 of 4
8

I would generally consider returning a pointer from a method in C++ a bad design, and mixing error states and payload data in the return value, too; this is a recipe for unmaintainable code.

Suggested change: Return the fail/success status as int value (or use ternary logic, e. g. boost::tribool), and pass the argument as non-const reference:

/** @returns
    - 1 if a solution has been found. The argument will be updated.
    - 0 if the request has been processed sucessfully, 
      but no (immediate) solution has been found.
      The argument is not modified in this case.
    - -1 if the request failed. The argument is not modified. */
int findSolution(MyClass& argument);

Usage example, leaving out premature optimization to avoid "unnecessary" copies:

MyClass objectToTest(originalUnmutableObject);

switch(findSolution(objectToTest))
{
    case 1:
        //Replace original with updated object, or whatever
        break;
    case 0:
        //Nothing to do (?)
        break;
    case -1:
        //Error handling
        break;
    default:
        //Unexpected return value
        assert(false);
}

An alternative, more sophisticated and reusable approach could be to bundle error state and object into a generic result class; this pattern was inspired by Rust. I leave the implementation of Result to you.

template<typename T>
class Result
{
    public:
        Result() = delete;
        Result(int error);
        Result(const T& data);
        Result(T&& data);

        //Methods
        bool isOk() const;
        bool isError(int error) const;
        int error() const;
        const T& data() const;

    private:
        //Variables
        int m_error = 0;
        T m_data;
};

...

Result<MyClass> findSolution(const MyClass& argument)
{
    int errorCode = 0;

    ...

    if(errorCode != 0)
        return Result(errorCode);
    else if(solutionFound)
        //Error code of result will be 0, Result::isOk() == true
        return Result(update(argument, solution));
    else
        //Error code of result will be 1, Result::isOk() == false
        return Result(1);
}
🌐
Unstop
unstop.com › home › blog › null pointer in c | a detailed explanation with examples
Null Pointer In C | A Detailed Explanation With Examples // Unstop
May 3, 2024 - We then use two separate if-statements to check if each pointer is equal to NULL, using the relational equality operator. Inside each if block, if the condition is true (i.e., the pointer is NULL), we print a string message indicating that the respective pointer is a null pointer. Finally, the main() function terminates with a return 0 statement, indicating successful execution to the operating system.
🌐
YouTube
youtube.com › watch
How to return NULL object in C - YouTube
Welcome to Mixible, your go-to source for comprehensive and informative content covering a broad range of topics from Stack Exchange websites. Our channel is...
Published   April 30, 2025