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 21): 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, ...
Discussions

How to return NULL object in C++ - Stack Overflow
I know that this might be a duplicate of: Return a "NULL" object if search result not found BUT, there's something different going on with my code because the asterisk doesn't solve my p... More on stackoverflow.com
🌐 stackoverflow.com
function cannot return null in c - Stack Overflow
This makes no sense at all. You need a complete redesign of your passing (and returning) approach. – AnT stands with Russia Commented Jan 31, 2017 at 22:32 ... Maybe there are some basic things you should rethink: First, only pointers can be NULL, but not objects. More on stackoverflow.com
🌐 stackoverflow.com
Difference between return 1 and return NULL
"Here is the portion that I need help with" Which is..? If you want to understand the difference between returning null and 1, then: Your method say "I will return a memory address, where a person can be found" - this is what person *create_family means. In C world, NULL means "There is nothing on this memory address, don't try to use it as valid data." The reason giving it might vary, but in case of malloc (which you call) it means "I could not allocate memory for you." - meaning you cannot create a person as expected. If you are returning 1, it means "there is a person at address 1` , which is clearly not the case. There is no person anywhere, as memory could not be allocated for it. Your program will have undefined behaviour as soon as you try to use that (invalid) memory address - which will result in "Segmentation fault" most likely. More on reddit.com
🌐 r/C_Programming
6
0
November 15, 2023
c++ - Return a "NULL" object if search result not found - Stack Overflow
I'm pretty new to C++ so I tend to design with a lot of Java-isms while I'm learning. Anyway, in Java, if I had class with a 'search' method that would return an object T from a Collection ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
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!
🌐
W3Schools
w3schools.com › c › c_null.php
C NULL
You can compare a pointer to NULL to check if it is safe to use. Many C functions return NULL when something goes wrong. For example, fopen() returns NULL if a file cannot be opened, and malloc() returns NULL if memory allocation fails.
Top answer
1 of 9
29

I think you need something like

Normal* Sphere::hit(Ray ray) {
   //stuff is done here
   if(something happens) {
       return NULL;
   }
   //other stuff
   return new Normal(something, somethingElse);
}

to be able to return NULL;

2 of 9
29

There are several fairly standard ways of doing this. There are different tradeoffs for the methods, which I'm not going to go into here.

Method 1: Throw an exception on failure.

Normal Sphere::hit(Ray ray)
{
   //stuff is done here
   if(something happens) {
       throw InvalidIntersection;
   }
   //other stuff
   return Normal(something, somethingElse);
}

void example(Ray r)
{
   try {
     Normal n = s.hit(r);
     ... SUCCESS CASE ...
   }
   catch( InvalidIntersection& )
   {
      ... FAILURE CASE ...
   }
}

Method 2 return a pointer to a newly allocated object. (You could also use smart pointers, or auto_ptrs to make this a little neater).

Normal* Sphere::hit(Ray ray)
{
   //stuff is done here
   if(something happens) {
       return NULL
   }
   //other stuff
   return new Normal(something, somethingElse);
}

void example(Ray ray)
{
  Normal * n = s.hit(ray);
  if(!n) {
     ... FAILURE CASE ...
  } else {
    ... SUCCESS CASE ...
    delete n;
  }
}

Method 3 is to update an existing object. (You could pass a reference, but a convention I use is that any output parameter is passed by pointer).

bool Sphere::hit(Ray ray, Normal* n)
{
   //stuff is done here
   if(something happens) {
       return false
   }
   //other stuff
   if(n) *n = Normal(something, somethingElse);
   return true;
}

void example(Ray ray)
{
  Normal n;
  if( s.hit(ray, &n) ) {
     ... SUCCESS CASE ...
  } else {
     ... FAILURE CASE ...
  }
}

Method 4: Return an optional<Normal> (using boost or similar)

optional<Normal> Sphere::hit(Ray ray)
{
   //stuff is done here
   if(something happens) {
       return optional<Normal>();
   }
   //other stuff
   return optional<Normal>(Normal(something, somethingElse));
}

void example(Ray ray)
{
  optional<Normal> n = s.hit(ray);
  if( n ) {
     ... SUCCESS CASE (use *n)...
  } else {
     ... FAILURE CASE ...
  }
}
🌐
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
November 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';
    }
}

Top answer
1 of 9
76

In C++, references can't be null. If you want to optionally return null if nothing is found, you need to return a pointer, not a reference:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

Otherwise, if you insist on returning by reference, then you should throw an exception if the attribute isn't found.

(By the way, I'm a little worried about your method being const and returning a non-const attribute. For philosophical reasons, I'd suggest returning const Attr *. If you also may want to modify this attribute, you can overload with a non-const method returning a non-const attribute as well.)

2 of 9
57

There are several possible answers here. You want to return something that might exist. Here are some options, ranging from my least preferred to most preferred:

  • Return by reference, and signal can-not-find by exception.

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

It's likely that not finding attributes is a normal part of execution, and hence not very exceptional. The handling for this would be noisy. A null value cannot be returned because it's undefined behaviour to have null references.

  • Return by pointer

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

It's easy to forget to check whether a result from getAttribute would be a non-NULL pointer, and is an easy source of bugs.

  • Use Boost.Optional

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

A boost::optional signifies exactly what is going on here, and has easy methods for inspecting whether such an attribute was found.


Side note: std::optional was recently voted into C++17, so this will be a "standard" thing in the near future.

Find elsewhere
🌐
Reddit
reddit.com › r/c_programming › can you return null from a function that returns a multidimensional ***pointer?
r/C_Programming on Reddit: Can you return NULL from a function that returns a multidimensional ***pointer?
January 17, 2022 -

I am very sure that someone told me once that NULL is defined as a pointer to void. I leafed through the K&R, and NULL was just said to be interchangeable with zero.

But either way, if I have a function that returns a 3d char array (array of arrays of strings), can I then return NULL if something goes wrong? will it be a valid return type?

Many functions that return pointers return NULL if something goes wrong - fopen for instance where you check for NULL and then perror.

But I am confused about multi-dimensional pointers.

I mean, I know that they are technically just pointers. I am unsure what the multiple asterisks do except tell the programmer how many dimensions there are. Hmmm Is this the solution?

Comments?

🌐
Stack Overflow
stackoverflow.com › q › 7425241
Newest Questions - Stack Overflow
Stack Overflow | The World’s Largest Online Community for Developers
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);
}
🌐
Bytes
bytes.com › home › forum › topic
how can I return nothing? - Post.Byes
September 19, 2007 - No. 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').
🌐
Quora
quora.com › Can-you-return-null-in-C
Can you return null in C++? - Quora
Answer (1 of 10): If you are interfacing with C and dealing with pointers you can return a pointer to an object. That pointer can be NULL, if the function fails or actually succeeds but returns a null value. Because NULL is universally represented as a pointer to address [code ]0x00000000[/code]...
🌐
Reddit
reddit.com › r/c_programming › return null versus return
r/C_Programming on Reddit: return NULL versus return
November 19, 2023 -

While freeing memory, this is how I proceeded:

// Free `p` and all ancestors of `p`.
void free_family(person *p)
{
    // TODO: Handle base case
    if (p == NULL)
      {
        return NULL;
      }

It appears (ChatGPT) that the following will be the correct way:

// Free `p` and all ancestors of `p`.
void free_family(person *p)
{
    // Handle base case
    if (p == NULL)
    {
        return;
    }

In the context of freeing memory, you typically don't return anything (NULLor otherwise) because you are modifying memory, not producing a result (ChatGPT).

The distinction seems subtle and somewhat vague though makes sense.

Source: https://learning.edx.org/course/course-v1:HarvardX+CS50+X/home

🌐
Wikipedia
en.wikipedia.org › wiki › Null_object_pattern
Null object pattern - Wikipedia
June 21, 2026 - These references need to be checked to ensure they are not null before invoking any methods, because methods typically cannot be invoked on null references. The Objective-C language takes another approach to this problem and does nothing when sending a message to nil; if a return value is expected, ...
🌐
Odetocode
odetocode.com › blogs › scott › archive › 2019 › 08 › 07 › think-twice-before-returning-null.aspx
Think Twice Before Returning null
August 7, 2019 - In case you missed the opening paragraphs, returning null is like telling your callers "I’m not only giving up, but I’m going to stick you with a dangerous value, so handle with care, and good luck!". Future generations who work on the code will curse you and burn you in effigy. The null object pattern solves the problem by returning a real object reference, and the real object contains some safe defaults.
🌐
GeeksforGeeks
geeksforgeeks.org › c language › null-pointer-in-c
NULL Pointer in C - GeeksforGeeks
By specifically mentioning the NULL pointer, the C standard gives a mechanism using which a C programmer can check whether a given pointer is legitimate or not. The malloc() function returns the NULL pointer when the memory allocation is failed.
Published: January 10, 2025
🌐
Eskimo
eskimo.com › ~scs › cclass › notes › sx10d.html
10.4 Null Pointers
When we're done with the inner loop, if we reached the end of the pattern string (*p1 == '\0'), it means that all preceding characters matched, and we found a complete match for the pattern starting at start, so we return start. Otherwise, we go around the outer loop again, to try another starting position. If we run out of those (if *start == '\0'), without finding a match, we return a null pointer.