Live data from Hacker News

Pointers Are More Abstract Than You Might Expect in C

stefansf.de

1–10 of 267 posts

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

#2
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; or the compiler needs to optimise field layouts, loops, functions, allocations, register assignments and local variables; or your CPU doesn't use the lower 4 bits or upper 24 bits when addressing.

C has no way to shield common language constructs from these problems. So everything in the language is a little bit compromised. Program in C for long enough and you'll hit a lot of special special cases – usually in the worst way: runtime misbehavior. Type punning corruption, pointers with equal bit representations that are not equal, values that change mysteriously between lines of code, field offsets that are different at debug and release time.

When using fundamental language constructs, we shouldn't need to worry about these ugly special cases – but C is built around these ideas. The need to specify memory layouts, direct memory access and other low level access should be gated by barriers that ensure the language's representation and the machine representation don't tread on each other's toes.

Rust has a long way to go but is so much more robust at runtime. I think there's room for other languages to occupy a similar space but they're need to focus on no-std-lib no-runtime operation (not always the sexiest target).

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

#3

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 compiler needs to optimise ...

wants to. There fixed that for you ;-)

The weird special cases were largely(1) introduced recently by optimizer writers hijacking the standard in order to soften the semantics so that previously illegal optimizations would now be legal, by simply declaring the vast majority of existing C code as "undefined" and up for grabs.

Which is why the Linux kernel, among others, has to set special flags in order to get back to a somewhat sane variant.

(1) Except for those special architectures where the hardware is that weird, but in that case you typically know about it.

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

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

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

#5
When I compile the example, i get:

  0x7ffd0b57ebd0 0x7ffd0b57ebd8 0
OK, so gcc reordered a & b; I'll fix this by chaning the initialisation of p and q to:

  int *p = &a + 1;
  int *q = &b;
But when I now run the example, I get:

  gcc -o c c.c && ./c
  0x7ffe55eb0aa4 0x7ffe55eb0aa4 1

  gcc -O -o c c.c && ./c
  0x7ffcfeffd914 0x7ffcfeffd914 0
So, p==q only evaluates to 1 if optimisation is enabled.

  $ gcc --version
  gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0

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

#6
clang is a bit more sane:

   > cc pointereq.c 
   > ./a.out 
   0x7ffee83163b8 0x7ffee83163b8 1
   > cc -O pointereq.c 
   > ./a.out 
   0x7ffeeeb8b3b8 0x7ffeeeb8b3c0 0
So without optimization, the pointers are the same and compare as equal. With optimization, the pointers compare as not equal. At first that seemed horrible, until I saw the pointers actually are not the same. Since I don't recall any guarantees about stack layout, that seems perfectly fine.

   > cat pointereq.c 
   
   #include 
   
   int main(void) {
     int a, b;
     int *p = &a;
     int *q = &b + 1;
     printf("%p %p %d\n", (void *)p, (void *)q, p == q);
     return 0;
   }

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

#7
post #5

When I compile the example, i get: 0x7ffd0b57ebd0 0x7ffd0b57ebd8 0 OK, so gcc reordered a & b; I'll fix this by chaning the initialisation of p and q to: int *p = &a + 1; int *q = &b; But when I now run the example, I get: gcc -o c c.c && ./c 0x7ffe55eb0aa4 0x7ffe55eb0aa4 1 gcc -O -o c c.c && ./c 0x7ffcfeffd914 0x7ffcfeffd914 0 So, p==q only evaluates to 1 if optimisation is enabled. $ gcc --version gcc (Ubuntu 7.3.0…

It shows the exact options the author used if you click on GCC:

Version: 8.1.1 Options: -std=c11 -O1 Target: x86_64-redhat-linux

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

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

Modern CPUs, but it used to be that they were designed for any high level language before C took over the show.

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

#9
post #3

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 compiler needs to optimise ... wants to. There fixed that for you ;-) The weird special cases were largely(1) introduced recently by optimizer writers hijacking the standard in order to soften the semantics so that previously illegal optimizations would now be legal, by simply declaring the vast majority of existing C code as "undefined" and up for grabs. Which is why the Linux kernel, among others, has to set…

What does "softening" the semantics mean? Aren't they pretty unambiguously defined by the standard?
Post reply on HN