Home > Back-end >  c doesn't set some of the array elements to nullptr
c doesn't set some of the array elements to nullptr

Time:03-18

Inside of int main() i declared double* arr = new double[2]; (an array that its items should be set to double or to nothing)

then i tried to change the values of the array elements from another function void func(double* arr_pointer[2]) by setting them to

arr_pointer[1] = nullptr;
arr_pointer[0] = nullptr;

but after i checked whenever their values changed to nullptr (in the main function) by printing out

cout << (nullptr == &arr[0]) << ' ' << (nullptr == &arr[1])

i got 1 0 in the console, why?

minimal reproducible example:

#include <iostream>

void func(double* arr_pointer[2], double& abc) {
    if (abc > 0) {
        (*arr_pointer)[0] = 20;
        (*arr_pointer)[1] = 22;
    }
    else if (abc == 0) {
        (*arr_pointer)[0] = 10;
        arr_pointer[1] = nullptr;
    }
    else {
        arr_pointer[1] = nullptr;
        arr_pointer[0] = nullptr;
    }
}

int main() {
    double* arr = new double[2];
    double abc = -1.2;
    func(&arr, abc)
    std::cout << (nullptr == &arr[0]) << ' ' << (nullptr == &arr[1])
}

CodePudding user response:

double* arr = new double[2];

(an array that its items should be set to double or to nothing)

arr is a pointer to a double. It points to the first element of an array of 2 doubles. The elements are double objects; they cannot be "nothing" objects. Furthermore, the array doesn't contain any pointers.

Sidenote: Avoid owning bare pointers. Prefer using std::vector.

void func(double* arr_pointer[2])

Function parameters of array types are adjusted to be pointers to element of such array. The parameter of this function is double** i.e. pointer to pointer to double.

You will not be able to call func(arr) because a double* is not implicitly convertible to double**.

cout << (nullptr == &arr[0]) << ' ' << (nullptr == &arr[1])

You are comparing the addresses of the array elements with null. The address of neither element should compare equal to null unless you've modified arr after its initialisation.


Regarding your edit:

func(&arr, abc)

arr is a singular pointer object. It is not an element in an array of multiple pointers.

arr_pointer[1] = nullptr;

arr_pointer[1] points past the end of the arr object, and assigning to it causes undefined behaviour. If the output of the program is something that you don't expect, it's probably because the behaviour of the program is undefined. If the program is what you do expect, it's probably in spite of the behaviour being undefined. Don't do this.

arr_pointer[0] = nullptr;

Since arr_pointer points to arr, indirecting through arr_pointer and assigning will cause arr to be assigned. In other words, this will set arr to point to null. Since arr was the sole pointer to the dynamic array, this means that the allocation can no longer be deallocated; This is a memory leak.

After this assignment, it's questionable whether &arr[0] is allowed because that subscript operator would be indirecting through a null pointer. However if we assume it to be allowed, then it's reasonable that arr == nullptr implies &arr[0] == nullptr.

CodePudding user response:

Note that the parameter double* arr_pointer[2] is not an array of two pointers, it is a pointer to a pointer to double; it is equivalent to double** arr_pointer.
(You can't pass arrays to functions; the [] notation is only a hint to the human reader that the argument is supposed to be an array.)

Your code has undefined behaviour, so it can output anything.
Perhaps this is best explained by inlining the function:

int main() {
    double* arr = new double[2];
    double abc = -1.2;

    double** arr_pointer = &arr;
    // Now, *arr_pointer, a.k.a. arr_pointer[0], is the same as arr
    // and *(arr_pointer   1), a.k.a arr_pointer[1], does not exist.
    // It is undefined to dereference arr_pointer   1.
    
    if (abc > 0) {
        (*arr_pointer)[0] = 20; // arr[0] = 20
        (*arr_pointer)[1] = 22; // arr[1] = 20
    }
    else if (abc == 0) {
        (*arr_pointer)[0] = 10; // arr[0] = 10
        arr_pointer[1] = nullptr; // arr_pointer[1] does not exist - undefined
    }
    else {
        arr_pointer[1] = nullptr; // arr_pointer[1] does not exist - undefined
        arr_pointer[0] = nullptr; // arr = nullptr
    }
    
    std::cout << (nullptr == &arr[0]) << ' ' << (nullptr == &arr[1])
}
  • Related