5 ms·
Not every high-level language gives you byte-level access to the representation of memory objects. But it is also wrong to reduce a language to what is in the
by uecker 2mo ago
Not every high-level language gives you byte-level access to the representation of memory objects.
But it is also wrong to reduce a language to what is in the spec.
- pjmlp 2mo agoMany do, contrary to what many C advocates talk about. Apparently reducing the language to what is in the spec is only a thing when talking about C and to some extent C++. When other languages have compiler specific extensions beyond the spec, it is a failure in their design. Yet when C and C++ devs have to reach out to compiler specific extensions, it is not a design failure like it is pointed out to others, rather an advantage. It is also wrong to not apply the same measure when it doesn't suit the message.
- uecker 2mo agoLot of stawman arguments.
- embedding-shape 2mo agoWouldn't be a authentic pjmlp comment unless they shit on C/C++ and/or praise Java/.NET with a bunch of straw-men :)
- pjmlp 2mo agoHow wrong you are, C++ isn't in the same league as C, Microsoft was right not wanting to keep updating their C support. It was already outdated by the time Borland released Turbo C++ 1.0 for MS-DOS, and only got new wind thanks to GNU FOSS and their manifest to prefer C as the main compiled language for GNU projects. Everywhere else outside UNIX, was going with a mix of C++ for OS frameworks, Apple, Microsoft, IBM, Be, Nokia, Epoch,.... Naturally given the option, between C, C++ and something else I might prefer that something else, however I managed a few interesting positions exactly due to my C++ skills, and interests. So don't mix my preferences for C and C++ on the same basket.
- embedding-shape 2mo agoWouldn't trade it for anything <3 Enjoy your Tuesday mate :) > So don't mix my preferences for C and C++ on the same basket. That mistake is mine indeed, I'll remember. Thanks, and I hope "no harm meant" was implicit :)
- gchamonlive 2mo ago> Wouldn't be a authentic pjmlp comment unless... > and I hope "no harm meant" was implicit :) Ad hominen then an apology, mixed signals here or I'm missing something. Maybe sarcasm?
- throwlifeaway 2mo ago> Ad hominen then an apology, mixed signals here or I'm missing something. Maybe sarcasm? You can express annoyance at someone's pattern of behavior without it being personal. embedding-shape isn't the only person annoyed by pjmlp's repeated disdain and snark towards people who use C (or Zig or WebAssembly or Rust or...).
- gchamonlive 2mo agoI didn't see snark prior to being provoked, but this seems like a discussion with history beyond this scope so I think I'd better sit this out
- pjmlp 2mo agoUsually I reply in the same tone as I get talked with, I have no qualms with touchy feeling culture of modern times.
- gchamonlive 2mo agoThat explains the escalations
- throwlifeaway 2mo ago
- pjmlp 2mo agoReally?! That is how many in C circles, including your regular comments to my comments happen to be like. Two measures two weights, in C versus other systems languages.
- uecker 2mo agoMaybe provide a concrete example instead of making vague accusations. Or rather, please not, it is not a useful discourse. A productive response to my comment would be an insightful explanation of how byte-level access to memory objects is done in other languages.
- muvlon 2mo ago> explanation of how byte-level access to memory objects is done in other languages. I'm not pjmlp but I can explain this for the case of Rust, where this works a bit like C but with a few interesting differences. Mainly, in Rust there is not a concept of a "memory object" per se in the runtime semantics. Memory is made of allocations and allocations are made of bytes. Unlike C, bytes are guaranteed to be 8 bits in size. Every byte of memory can hold integer values (0x00 to 0xff), pieces of a pointer or be uninitialized. That means there is nothing like strict aliasing, and therefore no need to have special rules for byte-level access. You can alias any type as any other type, so long as you avoid all the other sources of UB (out-of-bounds access, uninitialized memory access etc.). The way to practically access this is much the same as in C. You can do things like cast pointers between different types and project a pointer to a struct to a pointer to one of its fields. It should be noted that, unlike with major C implementations, structs do not have a stable, well-defined layout, so if you do manual pointer math you need to put #[repr(C)] on the struct to get C layout rules (which might still yield platform-dependent field offsets, e.g. size_t is not the same size everywhere). Note also that these are the dynamic rules of Rust, you need to follow these when writing unsafe code to avoid UB. The static rules of safe Rust are much more restrictive and don't allow much at all. It is possible to write unsafe code that exposes safe abstractions for this, one example is the "bytemuck" crate. It provides macros that can parse a type definition to check certain properties (e.g. well-defined layout, no padding) and then provide you with safe functions for byte-level access. Since there is no strict aliasing, for certain types you can also get safe functions for access at other granularities. For example: #[repr(C)] struct Foo { x: u32, y: u16, z: u16 } can be safely accessed as an array of u32 values (uint32_t in C), but #[repr(C)] struct Bar { x1: u16, x2: u16, y: u16, z: u16 } can not, for alignment reasons.
- sylware 2mo ago"When other languages have compiler specific extensions beyond the spec, it is a failure in their design." This one of the failures of Linus T. with the linux kernel: he was not able to keep the assembly source code with plain and simple C code you can compile with a small and alternative C compiler (same failure for the glibc devs I think). I don't blame him, he is already keeping the linux ABI stable, and pulling that off is something.
- jstimpfle 2mo agoMany other languages only have one compiler available to start with. Each additional compiler supported by a project means variance in functionality and thus additional work for the project. That work could make the codebase more robust. Or it could be a ton of useless work. Or anything in between. Depends on the context of the project.
- Dylan16807 2mo ago> assembly source code with plain and simple C code you can compile with a small and alternative C compiler Which part of that big clause is the part that failed? Because I thought you could still compile Linux with TCC.
- sylware 2mo agoAs far as I know, that was for x86(32bits) linux, that decades ago. With those assembly source files (which do not abuse any pre-processor) and plain and simple C, I could build a modern x86_64 linux kernel with cproc/qbe (which gets 70% of gcc speed in my CPU intensive benchmarks... for a few % of gcc code and in plain and simple C, not brain damaged c++). But I kind of don't mind since the future is assembly coding on non-IP-locked standard like RISC-V, and the main issue for that future is the abuse of pre-processors (ffmpeg was bitten by it) or code generators which would not be written in assembly themselves (or with a simple high level language with an assembly written interpreter, asmpython?).
- Dylan16807 2mo ago
- jstimpfle 2mo ago_You_ do that. All the time. And then you fight these strawmans.
- pjmlp 2mo agoAnd you reply to that all the time with the C bias as well, oh well.
- groundzeros2015 2mo agoYou comment this almost everyone it comes up. The hardware also isn’t x86! That’s an abstraction too. The point is in C you have greater control of execution and resources, not that it matches the hardware exactly. It’s a spectrum and C is closer on that spectrum than JavaScript.
- pjmlp 2mo agoBecause just like your comment proves the point, many think only C can do this. So I keep re-educating folks that isn't the case. Every thread has different people reading it, so there is always a first time for many of them.
- jstimpfle 2mo agoYou are again misreading even the most clearly put statement. Compared to e.g. Javascript, C is "closer" to the hardware, gives you "more control" of it. It would be completely ridiculous to deny this fact. And if you move to e.g. C# / Java or similar, if you squint, and you try to be a smart-arse, then you could deny that C is closer to the hardware than C#, because C# probably has everything you need to control it, to the same degree that C allows you to. But if you work in these languages for a while, and look at the code that you ended up producing, then again you will absolutely find that it would be ridiculous to not admit that C gives you better control. And you could even extend this to Rust, because the language encourages you to use high-level prefabricated components. It discourages you from doing low-level things, at least a little bit I think (I'm not a Rust user). I think what you are doing all the time, is you are being a smart-arse, nothing else. What interesting low-level performant things have you actually programmed lately?
- pjmlp 2mo agoSmart-arse is comparing C versus JavaScript, instead of C vs C++, for example. And then coming with such lengthy ad hominem. Let make a fun exercise for the audience, given your performance remark. Paste a random C code that I should replicate in whatever language I feel like. There is one rule. If the sample code is pure ISO C, then I will only use what is in the standard of whatever language I pick up. If the sample code makes use of single language extension not part of ISO C, then I will have the freedom to also pick whatever language extensions I feel like.
- FooBarWidget 2mo ago> Not every high-level language gives you byte-level access to the representation of memory objects. Any code that ventures anywhere near that territory is 99% Undefined Behavior. It's almost impossible to write proper C/C++ code that isn't UB while touching byte-level representations.
- uecker 2mo agoThis is certainly not true. Accessing bytes of objects is well-defined in C.
- FooBarWidget 2mo agoJust look at this: https://blog.habets.se/2026/05/Everything-in-C-is-undefined-behavior.html https://blog.habets.se/2026/05/Everything-in-C-is-undefined-... This is undefined behavior! const int* magic_intp = (const int*)bytes; Heck even something trivial like this is UB: bool bar(char ch) { return isxdigit(ch); } The only safe thing to do is memcpy, but that's super useless. As soon as you try to interpret or manipulate the byte-level data in any way, there are UB traps everywhere you go.
- uecker 2mo agoYes, using an arbitrary type that is different from the one of the object is UB. But any access of a representation byte using a character pointer is well defined, not just memcpy and I would also not call memcpy useless.
- deleted 2mo ago[deleted]