0

I'm newbie and I need little help. I tried different ways, but from what I can see NULL means 0 in c ++, so when want my (for example) int arr[4]=0, then it says that it's also NULL. Is there any way to see when value is 0 and not NULL (or empty?).

11
  • 1
    NULL and nullptr are a fancy way to spell 0 for pointers. There some minor differences between those spellings, but all of them represent the same pointer value (null), so you can't discern between them. Commented Jan 1, 2022 at 12:54
  • the only pointer in your example is arr, arr[4] is not a pointer but an integer value (that's hopefully inside the range of your array). Commented Jan 1, 2022 at 13:01
  • It is not possible to mark a value of an int as "empty". The assignment arr[0] = NULL will assign arr[0] to be zero, not mark it as "empty". Commented Jan 1, 2022 at 13:05
  • NULL isn't part of c++, and I don't think that int arr[4]=0 would compile, what's the intent there? If you can clarify your question, maybe in the process you could find an answer. Commented Jan 1, 2022 at 13:06
  • 1
    @PepijnKramer arr is an array, not a pointer. The name of an array can be used as if it is a pointer in some contexts but not others. But that does not mean an array is a pointer, nor vice versa. Commented Jan 1, 2022 at 13:07

3 Answers 3

3

Sounds like a job for std::optional:

#include <iostream>
#include <optional>

int main()
{
    std::optional<int> arr[] = { 10, 0, std::nullopt, -52 };

    for (auto i = 0U; i < sizeof(arr) / sizeof(*arr); i++)
    {
        if (arr[i])
        {
            std::cout << "arr[" << i << "] = " << *(arr[i]) << std::endl;
        }
        else
        {
            std::cout << "arr[" << i << "] = std::nullopt" << std::endl;
        }
    }
}

Output:

arr[0] = 10
arr[1] = 0
arr[2] = std::nullopt
arr[3] = -52
Sign up to request clarification or add additional context in comments.

1 Comment

Looks like a perfect solution to an XY problem.
1

It sounds like you're looking for a null concept for your data type (int array[4]), but you want 0 to be a valid (non-null) value. The null concept is useful when your variable is not guaranteed to hold valid data. You need a null concept if, for a variable x, you want to be able to ask the question "does x contain a valid value?".

First, recognize that NULL is an implementation-defined way to represent a pointer that points at nothing. Here, implementation means "specific compiler". Usually, NULL is an integer constant equal to 0, which in practice makes it ill-suited to differentiate from your otherwise-valid value of 0.

TL;DR: I think you want to use std::vector, but you have several options available.

Null concept for int

Depending on what your data represents, you may be able to represent a null by selecting a value or range of values that are not valid for your specific use case, but otherwise representable using your data type.

Some example null concepts for int data type:

  • 0-- is a perfectly fine null when 0 is not a valid value. The null test code is very clean as well: if (x) { ... }.
  • negative values-- You can select a specific negative value or the entire range of negative values. Or even a subrange of all negative values, although I've never seen this last one in practice. Generally the specific value of -1 is used. The null test code looks like: if (x >= 0) { ... } or if (x != -1) { ... }.
  • extreme positive values-- You can select a very large number to represent the null concept. If a valid instance of your data will never reach this value. I recommend std::numeric_limits<int>::max(), which requires #include <limits>. The null test looks like: if (x != std::numeric_limits<int>::max()) { ... }

std::optional<T>

When all possible values of your data type represent valid values, then you need to include extra overhead if you want to represent the null concept. std::optional<T> wraps any data type and is used specifically for the case where you need to represent invalid data. The access semantics looks very similar to accessing a pointer.

#include <optional>

void do_something(int);

int main() {
    std::optional<int> a; // default initialization is "empty"
    std::optional<int> b = 1; // can be assigned just as if it were the type

    if (a) { // You can check in a natural-feeling way if the data is valid
        do_something(*a); // and access the data as if it were a pointer
        do_something(a.value()); // or use std::optional<T>::value()
    }

    // If the data may be invalid, you must check before accessing
    // *a; // WRONG: throws an exception
    // a.value(); // WRONG: for the same reason

    // If you know for certain the data is valid, feel free to access it
    do_something(*b);

    // You can't access it entirely as if it were an int, dereferencing is necessary
    // int c = b + 2; // invalid, no overloaded operator+ for std::optional<int> type
    int c = *b + 2; // valid

    // An array of optionals looks similar to an array of ints
    std::optional<int> array[4]; // initialized as all empty

Just don't deal with invalid data at all

If your data doesn't necessarily need to exist until it is valid then you can use a variable size container to just... not have invalid data at all.

std::vector<T> is the go-to dynamically sized container in C++, and allows you to have just enough space to handle only the data you need. std::vector<T> also has many class methods that allow easy access to container information such as std::vector<T>::size() or iterators with std::vector<T>::begin() and std::vector<T>::end().

#include <vector>

void do_something(int);

int main() {
    std::vector<int> data; // initially empty, no elements

    // you can add new values
    data.push_back(1); // vector contains { 1 }
    data.emplace_back(2); // vector contains { 1 , 2 }

    // looping is the same as with arrays
    for (int i = 0; i < data.size(); i++) {
        do_something(data[i]);
    }

    // or you can use range-based for loops for cleaner looking code
    for (auto& d : data) {
        do_something(d);
    }
}

Comments

0

If that is an array of pointers:

int* arr[10] = {};

Then here is how you check if an element is null:

if (arr[4] == nullptr) 

And here is how you check if the pointed value is zero:

if (*arr[4] == 0) // note the *

3 Comments

This answer shows an array of pointer to ints, whereas the OP had an array of ints (if I understood correctly)
@PepijnKramer arr[4] is a pointer in this example, and *arr[4] dereferences that pointer. Otherwise the code wouldn't compile.
@Sebastian I am guessing OP wants an array of pointers, otherwise the use of the null pointer is unclear.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.