Live data from Hacker News

Pointers Are More Abstract Than You Might Expect in C

stefansf.de

101–110 of 267 posts

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

#101
post #61

Earlier quoted context omitted.

Support for unaligned memory accesses in hardware is one. The exceeding majority of variable accesses are through pointers of the correct type, and are therefore to variables that are at least naturally aligned. But a very small handful of systems/procedures make unaligned accesses through type-punned pointers. Rather than just crash on these programs, processors will perform multiple memory accesses and stitch the r…

Afaik, sparcs and many other traditional unix-running cpus does not support unaligned memory access

Technically, neither does ARM. Although you can enable emulation for unaligned accesses. One of the first things I did when setting up QNX was enabling emulation for unaligned accesses to eliminate a SIGBUS termination on some of our applications.

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

#102
post #99

Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow…

My guess is type based alias analysis. The classic example is casting an int to a float like so may crash your program due to undefined behavior:

float my_bad_function(void) { int x = 5; float* y = (float) &x; return y; }

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

#103

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;…

> 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). You're describing the Zig language! It aims to be as fast as C, and unlike most languages that say this is a goal, it means it. There's no "almost as fast as C if you ignore the garbage-collector and the array-bounds-checking", it's actually as fast as C. I…

> faster even than hand-tuned assembly

I think you and I are working off different definitions of what that means, as my definition doesn't really allow for a faster implementation (unless there's some really spooky stuff going on in the compiler). I suspect you mean faster than a popular hand tuned implementation.

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

#104
post #95
post #80

Earlier quoted context omitted.

Why would you think that Rust is "far simpler" than C++? Exactly the same concepts (with extras on Rust's side because of the ML-like constructs) must be learned for both, except they're distributed differently on the learning curve. And I wouldn't say that Rust's safer than Java either. Memory access errors are basically non-existant in Java and it has quite robust concurrency primitives and libraries.

> Why would you think that Rust is "far simpler" than C++? C++ as a language is a lot more complicated. It has a lot of features with weird corner cases that interact in unfortunate ways. > And I wouldn't say that Rust's safer than Java either. Depends on what you mean with safe. If you mean memory safe, then they are about as safe. Rust has fewer runtime failures due to concurrency and null pointers though.

Not sure why the above comment is downvoted. The number of features in C++ isn't the root of the problem with C++. The real problem with C++ is that it both has a lot of features and that all of those features interact in subtle and surprising ways. Even if Rust had as many features as C++ (which it doesn't, not by a long shot; Rust is a medium-sized language like Python (though with a far less forgiving learning curve than Python)), one of the design philosophies of Rust is that features should interact in predictable ways, and if two features can't interact in predictable ways, then the compiler should do its damndest to prevent them from being used together and explain why.

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

#105
post #37

There's nothing surprising in the first example. Comparing the addresses of stack variables is undefined behaviour. The second one is more interesting: extern int _start[]; extern int _end[]; void foo(void) { for (int *i = _start; i != _end; ++i) { /* ... */ } } GCC optimized "i != _end" into "true". The kernel guys fixed this by turning "_start" and "_end" into "extern int*". I always thought [] was just syntactic s…

> I always thought [] was just syntactic sugar over a regular pointer, but seems like I was wrong.

It depends on the context. When used in function arguments, yes, it's the same. When used during the declaration of a variable, it's entirely different.

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

#106

Earlier quoted context omitted.

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.

> 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 This just means that the Rust language does not have the feature of being simple. Of course, there are sane subsets of C++ also (e.g., do not use new/delete), but this does not mean that C++ is a sane language. The same goes for Rust, probably.

> The same goes for Rust, probably.

Well, at least you have the good grace to admit that you haven't used Rust. :P

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

#107

Earlier quoted context omitted.

The stack is one of those things that would fall under "support for common paradigms". I checked that PDP-11 (the machine on which C was created) already had a hardware stack - and probably even older machines. There are many other programming languages that have the concept of a call stack. Hardware stacks are just an optimization to support this paradigm, and you are not required to use it. Conversely, C does not r…

"The stack is one of those things that would fall under "support for common paradigms"." Maybe for imperative languages where there is no support for lambda expressions (like C), but in Lisp or in functional languages call stacks are not part of the basic semantics. To put this in C terms, compilers for those languages will rewrite functions to take an extra argument called the "continuation", which is itself a point…

Call stacks are almost always used in implementations of functional languages as well, even those that support first-class continuations. Even implementations that use CPS as you describe don't necessarily lose call-stack discipline (e.g. guile); that's a separate choice that some (e.g. SML/NJ) choose to make.

The call stack provides very cache-friendly and gc-friendly memory. It's still a very useful construct in functional languages.

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

#108
post #70
post #37

There's nothing surprising in the first example. Comparing the addresses of stack variables is undefined behaviour. The second one is more interesting: extern int _start[]; extern int _end[]; void foo(void) { for (int *i = _start; i != _end; ++i) { /* ... */ } } GCC optimized "i != _end" into "true". The kernel guys fixed this by turning "_start" and "_end" into "extern int*". I always thought [] was just syntactic s…

> I always thought [] was just syntactic sugar over a regular pointer, but seems like I was wrong. For another example showing their differences, if a.c has: int n[] = { 1 }; And b.c has: extern int *n; printf("%d\n", *n); Then running b.c will segfault, whereas if it said extern int n[], it would work as expected (hint: extern int n and printf("%d\n", n) would also work). Arrays degrade to pointers at the drop of a…

> Then running b.c will segfault

why would it not ? On one side you declare an int array of size 1, on the other side you declare a pointer. Think about what's going on with the bytes :

    int n[] = { 1 };
will look exactly the same in memory than

    int n = 1;
which is of course not compatible with

    int* n = 1; 

Arrays by themselves have no indirection in C.

=> https://godbolt.org/g/xwT7uW

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

#109
post #65

Earlier quoted context omitted.

That was the argument of C++ advocates in the 90s.

Considering that C doesn't have any good facilities for polymorphism, it's going to continue to be the argument of any language that succeeds C. Unless, that is, that successor language also doesn't have any good facilities for polymorphism, in which case we have Go as a fascinating real-world study in how people will incessantly demand them and deride the language for lacking them (which is saying something, conside…

Apparently under certain conditions it is possible to emulate a crude form of ad hoc polymorphism in C.

https://codegolf.stackexchange.com/questions/2203/tips-for-g...

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

#110

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;…

C sort of has this mindset built around it that you're writing portable assembly, except for messy bits like stack frame layout or register allocation. But that doesn't really hold true anymore, and arguably hasn't for decades. The first obvious issue is that C is specified by an abstract machine that doesn't really correspond to actual hardware. There's no concept of segmented memory, or multiple address spaces in C…

> flag bits

That's sort of a processor specific implementation detail, IIRC you can access them via GNU extensions.

> SIMD vectors

Not having SIMD IMO is a feature as doing useful things will expose processor specific details, you can use SWAR to do some of SIMD.

Post reply on HN