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])
}