www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Comparing pointers in C and D

reply Olivier Pisano <olivier.pisano laposte.net> writes:
Hello,

Today a colleague of mine gave me a link to this article about 
comparing pointers in C :

https://pvs-studio.com/en/blog/posts/cpp/0576/


Playing with the first code example in Compiler explorer, it 
seems that the pointer comparison is always false in GCC once 
optimizations are enabled, while it is always true with Clang, no 
matter the optimization level.

What bothers me is that the same behavior can be observed 
respectively with GDC (false) and LDC (true), at least with the 
versions available in compiler explorer.

Does the D spec define pointer comparison semantics ? What should 
the correct behaviour be? I can understand the C standard wording 
in regards to segmented memory archs, but I must admit I have 
trouble justifying it on a PC with linear address space...

Best regards.
Feb 15 2023
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/15/23 12:07, Olivier Pisano wrote:

 https://pvs-studio.com/en/blog/posts/cpp/0576/
I haven't read the article but the example has the following: int a, b; int *p = &a; int *q = &b + 1; As far as I know, that pointer arithmetic applied to a single object is undefined behavior. (I would love to learn otherwise if I am mistaken there. But I've just checked again, an expression like '&b + 1' can only be applied to pointers into array elements. Since b is not an array element, I am confident that it's undefined behavior.) If so, I think both gcc and llvm are aware of undefined behavior and it looks trivial to catch the one above. If they detect undefined behavior, they can produce any result. But I don't know whether they apply that logic. (?) Ali
Feb 15 2023
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 16/02/2023 2:13 PM, Ali Çehreli wrote:
      int a, b;
      int *p = &a;
      int *q = &b + 1;
 
 As far as I know, that pointer arithmetic applied to a single object is 
 undefined behavior.
safe will of course prevent this. So as far as D is concerned its a solved problem ;)
Feb 15 2023
prev sibling next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 16 February 2023 at 01:13:17 UTC, Ali Çehreli wrote:
 On 2/15/23 12:07, Olivier Pisano wrote:

 https://pvs-studio.com/en/blog/posts/cpp/0576/
I haven't read the article but the example has the following: int a, b; int *p = &a; int *q = &b + 1; As far as I know, that pointer arithmetic applied to a single object is undefined behavior.
In C the addition itself is defined behavior (you are allowed to create a pointer to "one past the end" of an object), but dereferencing it would be UB. [1] The D spec does not say anything about this, but I think it's safe to assume that it inherits C's semantics.
Feb 15 2023
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/15/23 22:28, Paul Backus wrote:

 In C the addition itself is defined behavior (you are allowed to create
 a pointer to "one past the end" of an object)
To be pedantic, "one past" is always applied to "the last element of the array object". My reaction was to the non-array object in the code. :)
 it's safe to assume that it inherits C's semantics.
I think so too. Ali
Feb 15 2023
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 16 February 2023 at 06:46:16 UTC, Ali Çehreli wrote:
 On 2/15/23 22:28, Paul Backus wrote:

 In C the addition itself is defined behavior (you are allowed
to create
 a pointer to "one past the end" of an object)
To be pedantic, "one past" is always applied to "the last element of the array object". My reaction was to the non-array object in the code. :)
"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."
Feb 15 2023
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 2/15/23 22:56, Paul Backus wrote:

 "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."
 

That's helpful. Thanks! :) Ali
Feb 15 2023
prev sibling parent reply Olivier Pisano <olivier.pisano laposte.net> writes:
If I change the variable types by arrays of 1 int, I get the same 
result :

https://godbolt.org/z/YWTvTPr4W

You are right, it is certainly a UB, but it seems that the GCC 
optimizer treats scalars and arrays the same way, as soon as it 
can statically deduce the arithmetic goes past the end of the 
object memory space.
Feb 15 2023
parent reply Olivier Pisano <olivier.pisano laposte.net> writes:
On Thursday, 16 February 2023 at 06:37:54 UTC, Olivier Pisano 
wrote:
 If I change the variable types by arrays of 1 int, I get the 
 same result :

 https://godbolt.org/z/YWTvTPr4W

 You are right, it is certainly a UB, but it seems that the GCC 
 optimizer treats scalars and arrays the same way, as soon as it 
 can statically deduce the arithmetic goes past the end of the 
 object memory space.
And now I start wondering how can STL algorithms even work since the end iterator is past the last element. Gosh...
Feb 15 2023
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 16.02.23 07:42, Olivier Pisano wrote:
 On Thursday, 16 February 2023 at 06:37:54 UTC, Olivier Pisano wrote:
 If I change the variable types by arrays of 1 int, I get the same 
 result :

 https://godbolt.org/z/YWTvTPr4W

 You are right, it is certainly a UB, but it seems that the GCC 
 optimizer treats scalars and arrays the same way, as soon as it can 
 statically deduce the arithmetic goes past the end of the object 
 memory space.
And now I start wondering how can STL algorithms even work since the end iterator is past the last element. Gosh...
You shouldn't run into this kind of issue as long as you only compare iterators from the same container, don't go past the end by more than one element and don't dereference past-the-end iterators.
Feb 16 2023
prev sibling parent Dukc <ajieskola gmail.com> writes:
On Wednesday, 15 February 2023 at 20:07:35 UTC, Olivier Pisano 
wrote:
 Does the D spec define pointer comparison semantics ? What 
 should the correct behaviour be? I can understand the C 
 standard wording in regards to segmented memory archs, but I 
 must admit I have trouble justifying it on a PC with linear 
 address space...
I cannot find a relevant line in the spec. It should be defined behaviour, as it is allowed in ` safe`, but the result of the comparison is probably undefined, in the same way a `bool` variable initialised with ` = void` is undefined.
Feb 16 2023