DEV Community

Discussion on: Pointer in C/C++

Collapse
 
sandordargo profile image
Sandor Dargo

Good points, but I'd go even further.

When you wrote pa++ you derived a pointer value from pa and assigned it back to pa, meaning that it is still indexing the same array, but is now pointing one past the end of the array.

It doesn't really index an array, it doesn't know if it points to an array and which array. It just points to a memory address and interprets what is there as an integer - without even having any notion of the array the programmer wanted to point at.

This example starts to get funnier when you declare something right after this array. While that's unspecified where the variable will be stored, you can guess for the sake of the game.

int main() {


long ar[] = {1, 2, 3, 4, 5};
double d[]={4.2, 0.42};
long *ptr;
ptr = ar;
for (int i = 0; i < 7; i++)
{
    printf("Value of *ptr = %ld\n", *ptr);
    printf("Value of ptr = %p\n", ptr);

    // Increment pointer ptr by 1
    ptr++;
}

With gcc, it'll read in ds values and even though they are doubles, as the pointer is pointing at long values, it will interpret the doubles as longs. After all, in the memory they are just 0s and 1s... (Note that on clang, based on what I saw, d will have a lower memory address, so the loop will not find it)

Collapse
 
pentacular profile image
pentacular • Edited

I think you are inferring an incorrect model of how C works by observing how some popular implementations of C work.

Let's take a look at a freely available draft standard for C.

open-std.org/jtc1/sc22/wg14/www/do...

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

and

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

What this means is that:

  1. All C objects are effectively stored in arrays.
  2. You cannot legally get from one array to another array using pointer arithmetic.

What you're observing above is undefined behavior -- you may be able to get away with it with particular compilers and architectures, but it isn't how C works. :)

Thread Thread
 
sandordargo profile image
Sandor Dargo

That's perfectly right, we are speaking about two different things. You say that getting from one array to another via pointer arithmetics is undefined behaviour. It is! In fact, that's pretty much I talked about at C++ On Sea earlier this week. Except that, I didn't speak about arrays, but STL containers and not about pointer arithmetics, but iterators.

What I tried to point at here and I see I was not clear enough, is that a pointer or an iterator doesn't know about the container it points at. It only knows the memory address and the type that it is looking for.

Let's take a practical example. We have two containers of the same type, a and b and we have a pointer to each pa and pb. Can you write a function taking the pointers and decide whether the pointers belong to the same array without having any more info available about the arrays?

#include <iostream>
#include <array>

bool f(int* pa, int* pb) {
   // TODO
   // return true of pa and pb point at the same array, false otherwise
   return true;
}

int main() {
    int a[] = {1,2,3};
    int b[] = {4,5,6};
    int* pa = a;
    int* pb = b;
    if (f(pa,pb)) {
        std::cout << "pa and pb belong to the same array" << std::endl;
    } else {
        std::cout << "pa and pb belong to the same array" << std::endl;
    }
}

As far as I understand, this is not possible, because the pointers they don't belong to a container. And this doesn't change the fact, that it's the callers responsibility to use the pointer in a sane way not trying to depend on UB. In fact, I find it quite disturbing that the article mentions C++ whereas there is no reason in 2020 to use c-style arrays and pointer arithmetics to iterate over an array...

Thread Thread
 
pentacular profile image
pentacular

Can you write a function taking the pointers and decide whether the pointers belong to the same array without having any more info available about the arrays?

You cannot introspectively determine this.

Just like you cannot introspectively determine that a pointer has a well defined value, or that a pointer points at allocated memory.

As far as I understand, this is not possible, because the pointers they don't belong to a container.

It is not possible because C and C++ do not provide introspective mechanisms to determine this.

However, they do assert that you cannot legitimately derive a pointer to one array from a pointer to another array.

(And as all objects are effectively stored in arrays in C and C++, this is a universal property and applies likewise to the substructure of STL containers, and so on.)

Which means that the association exists, regardless of if it is encoded into the program in a detectable fashion or not.

Just as memory being allocated or not may not be encoded into the program in a detectable fashion.

(For example, consider a compiler which has been able to statically determine all memory allocation your program will perform and so has hard coded every allocation at compile-time.)

The fact that you can't check it doesn't mean that it isn't significant. :)