Live data from Hacker News

Pointers Are More Abstract Than You Might Expect in C

stefansf.de

21–30 of 267 posts

Re: Pointers Are More Abstract Than You Might Expect in C

#21
post #15

Basically you have no guarantee where the pointer q is pointing to. Some compiler/static code analyzer will yell at you with this code.

isn't it guaranteed that is points sizeof(int) bytes higher than the address of b? Whether something useful is behind that address is another question

There's a guarantee relative to the address of b. But there's no guarantee about the relative addresses of a and b themselves, i.e. where they are placed in automatic storage. So even setting aside the idea of optimizing the test away at compile time, there's no guarantee that the comparison result will be a specific value. a could be above or below b, and they are not necessarily adjacent objects.

Re: Pointers Are More Abstract Than You Might Expect in C

#22

This scratches the surface of why I hope C slowly fades away as the default low-level language. C sounds simple when you look through K&R C. C lets you feel like you understand the stack, ALU and memory. A pointer is just an integer and I can manipulate it like an integer. But the reality is filled with a staggering number of weird special cases that exist because memory doesn't work like a simple flat address space;…

The following is purely my opinion. Rust might have gone too far the other way. Yes it strives to be a modern language, with a lot of functional programming features and "OOP" done right (aka no inheritance, simply method polymorphism). To me Rust is more a C++ replacement than a C replacement. A replacement for C should try to be as simple as possible while fixing C weak typing mess with strong typing for instance,…

[deleted]

Re: Pointers Are More Abstract Than You Might Expect in C

#23

I like the behavior of the compiler here. There is no guarantee that a and b are next to each other in memory. That's why the comparison fails, the alternative makes is runtime/compiler/optimization level dependent which would be a total mess. As usual with those C bashing articles you won't run into trouble if you don't try very hard to write contrived code. I mean, the moment you see: int *q = &b + 1; on your scree…

That would require making a distinction between array-pointers and non-array pointers. There, another can of worms. Probably not worth the additional complexity.

Re: Pointers Are More Abstract Than You Might Expect in C

#24
post #21
post #15

Earlier quoted context omitted.

isn't it guaranteed that is points sizeof(int) bytes higher than the address of b? Whether something useful is behind that address is another question

There's a guarantee relative to the address of b. But there's no guarantee about the relative addresses of a and b themselves , i.e. where they are placed in automatic storage. So even setting aside the idea of optimizing the test away at compile time, there's no guarantee that the comparison result will be a specific value. a could be above or below b, and they are not necessarily adjacent objects.

From the C11 spec quoted in the article

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

So although most implementations might produce an address that's relative to b, that's not actually guaranteed by the spec unless it's `&b + 1`.

Re: Pointers Are More Abstract Than You Might Expect in C

#25

This scratches the surface of why I hope C slowly fades away as the default low-level language. C sounds simple when you look through K&R C. C lets you feel like you understand the stack, ALU and memory. A pointer is just an integer and I can manipulate it like an integer. But the reality is filled with a staggering number of weird special cases that exist because memory doesn't work like a simple flat address space;…

The following is purely my opinion. Rust might have gone too far the other way. Yes it strives to be a modern language, with a lot of functional programming features and "OOP" done right (aka no inheritance, simply method polymorphism). To me Rust is more a C++ replacement than a C replacement. A replacement for C should try to be as simple as possible while fixing C weak typing mess with strong typing for instance,…

You don't need to use any polymorphism (generics or traits) in Rust. You can use it as a pure structs and functions language like C (especially if you're not using the standard library).

The argument in favour of at least some polymorphism is that it helps to minimise highly repetitive code that would be avoided in C through aliasing, type punning or other pointer conversion.

Re: Pointers Are More Abstract Than You Might Expect in C

#26
post #4

This scratches the surface of why I hope C slowly fades away as the default low-level language. C sounds simple when you look through K&R C. C lets you feel like you understand the stack, ALU and memory. A pointer is just an integer and I can manipulate it like an integer. But the reality is filled with a staggering number of weird special cases that exist because memory doesn't work like a simple flat address space;…

But as you know, CPU ISAs are designed for C programs and compilers are optimized for C programs. So everything, even new languages like Rust, have to buy into C's model to some extent. Truly getting out from under C's shadow is going to be very difficult. Maybe better languages are a first step on that path but they are only a small step.

That is said a lot, but what are actual desicions that are made to conform to the C model?

What would be good ideas in CPU design that aren't made since they are not compatible with C?

(I get it that CPUs have to support some common paradigms and use cases. For example, virtual memory / process isolation, maybe branch prediction things, or support for calling conventions. However, I don't think that is specific to C).

Re: Pointers Are More Abstract Than You Might Expect in C

#27
post #19

Just a datapoint: VS2017 on Win10 x64 gives me 00AFF89C 00AFF894 0, which is what I naively expect.

Actually, you should not expect that, because you don't have a guarantee of ordering of the addresses of a and b on the stack. Now try with /O2 . (-:

Maybe I'm misunderstanding you, but it's precisely because I have no knowledge of the stack frame's layout that I didn't expect the pointers to be equal.

With /O2 optimisation I get:

00B1F99C 00B1F9A4 0

Re: Pointers Are More Abstract Than You Might Expect in C

#28
post #24
post #21

Earlier quoted context omitted.

There's a guarantee relative to the address of b. But there's no guarantee about the relative addresses of a and b themselves , i.e. where they are placed in automatic storage. So even setting aside the idea of optimizing the test away at compile time, there's no guarantee that the comparison result will be a specific value. a could be above or below b, and they are not necessarily adjacent objects.

From the C11 spec quoted in the article > 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. So although most implementations might produce an address that's relative to b, that's not actually guaranteed by the spec unless it's `&b + 1`.

... which it is in the program under discussion. Again, the address which has no guarantee relative to the address of b or the value of q is the address of a.

Re: Pointers Are More Abstract Than You Might Expect in C

#29
post #19

Earlier quoted context omitted.

Actually, you should not expect that, because you don't have a guarantee of ordering of the addresses of a and b on the stack. Now try with /O2 . (-:

Maybe I'm misunderstanding you, but it's precisely because I have no knowledge of the stack frame's layout that I didn't expect the pointers to be equal. With /O2 optimisation I get: 00B1F99C 00B1F9A4 0

That's where you are going wrong. You have no guarantee that the compiler places a and b next to each other, let alone in a defined order with a at a higher address than b such that one integer width beyond the end of b you find a.

Expecting one thing is wrong. You are expecting the one thing that the comparison always returns false. You should not expect anything. The comparison result could be true or false.

    H:\>cl /O2 pointereq.c
    Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26431 for x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    pointereq.c
    Microsoft (R) Incremental Linker Version 14.14.26431.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:pointereq.exe
    pointereq.obj
    
    H:\>.\pointereq
    00CFFA20 00CFFA20 1
    
    H:\>

Re: Pointers Are More Abstract Than You Might Expect in C

#30
post #17

the comparison at the start is nonsense - there is no specification for the ordering or location of stack variables. by taking the address of these variables, you could see that they actually are the same value, and so intuitively you’d think they might be the same, but a different compiler might put them in different locations. or they may be elided entirely through optimisation. it’s far safer to fail the equality…

Surely the point of writing an if-block testing the equality of the pointers is precisely because the code isn’t assuming that they are the same - but maybe it has something it wants to do if it finds itself running somewhere where they are.

Writing code which assumed those pointers were equivalent would be bad, but this code doesn’t do that. Instead, it looks like the compiler assumes that the pointers won’t be the same and refuses to let you entertain the possibility at all.

Post reply on HN