Live data from Hacker News

The beauty and simplicity of the good old C-style void* in C++

giodicanio.com

111–120 of 182 posts

Re: The beauty and simplicity of the good old C-style void* in C++

#111
post #46

Ick. The entire article starts from the fundamentally flawed premise that "you want a function that takes a blob of memory as an argument". Then they discuss bytewise access into structures.. Passing around void pointers is simply not a safe thing to do in C++. You can't do anything with a void pointer, so you're probably going to cast it as something else. Use that type instead, so that your caller knows they need t…

In general, you're right. The exception that I could think of is a "dump memory" function. You take a pointer to something (who cares what it is), and print out the bytes there. That I could see taking a void*. But that's a really limited case. In general, yes, you do not want to be dealing with blobs of memory as arguments. You want to be dealing with things that are known to be the right kind of thing as arguments.

But parent is right, you have to cast it anyways before reading from it, so might as well take the right type from the beginning.

Re: The beauty and simplicity of the good old C-style void* in C++

#112

The real question here is: WHY are you passing a blob of memory rather than a struct that uses the type system to describe and enforce what the contents are? I don't mean dressing up an anonymous pointer, which the author rightly complains about. I mean WHY are you making an API that takes such a pointer to an unknown type to begin with? Whenever you change the structure within that blob, your type checker won't flag…

For type erasure (it’s sometimes useful), custom allocators, I/O, for example.

Re: The beauty and simplicity of the good old C-style void* in C++

#113
post #106

The real question here is: WHY are you passing a blob of memory rather than a struct that uses the type system to describe and enforce what the contents are? I don't mean dressing up an anonymous pointer, which the author rightly complains about. I mean WHY are you making an API that takes such a pointer to an unknown type to begin with? Whenever you change the structure within that blob, your type checker won't flag…

I think the article names hashing as a use-case, which I can somewhat still agree. Operations that only depend on the bytes, I guess. But yeah, most things worth saying about this article have been said here already

Even then, accepting a uint8_t* would make this intent clearer.

Re: The beauty and simplicity of the good old C-style void* in C++

#114
post #8

> Why should people complexify and uglify their C++ code with the uint8_t pointer (or std::byte), when void* works just fine?? Fair point (although to be honest: 'complexify' feels a bit of an exaggeration here to me), but the answer to this why is simple: document and express intent clearly. The compiler gave you an error first such that you're forced to consider what you're doing. Any seasoned C++ developer seeing…

I don't have a strong opinion what is better in this case, but my view is: > document and express intent clearly Arguably, the void* does that as well? > Any seasoned C++ developer seeing this knows what this reinterpret_cast means. Same for void*? > it's a bit more text to read If you have to call it many times, this adds up. > Some might also say it complexifies and uglifies the code I think the point is that it ad…

> Arguably, the void* does that as well?

How do you figure? The type is a pointer to quite literally anything, including nothing (ie a pointer that cannot be dereferenced). If you're working with bytes, indicate this with the type.

Re: The beauty and simplicity of the good old C-style void* in C++

#115
post #8

> Why should people complexify and uglify their C++ code with the uint8_t pointer (or std::byte), when void* works just fine?? Fair point (although to be honest: 'complexify' feels a bit of an exaggeration here to me), but the answer to this why is simple: document and express intent clearly. The compiler gave you an error first such that you're forced to consider what you're doing. Any seasoned C++ developer seeing…

Span will increase compilation time for no useful reason. It’s not any safer at the call site.

Well if compilation time is an issue, you chose the worst possible language to use. But if you must use C++, you should use the mechanisms that best communicate intent.

Re: The beauty and simplicity of the good old C-style void* in C++

#116

The real question here is: WHY are you passing a blob of memory rather than a struct that uses the type system to describe and enforce what the contents are? I don't mean dressing up an anonymous pointer, which the author rightly complains about. I mean WHY are you making an API that takes such a pointer to an unknown type to begin with? Whenever you change the structure within that blob, your type checker won't flag…

> Whenever you change the structure within that blob, your type checker won't flag that the receiver hasn't been updated to handle it.

The relevant type is "blob". There is no further structure. If the function that accepts void* is trying to extract structure out of the blob, there is a bug in that function and the type checker should already catch you trying to extract structure from something that isn't there.

> I mean WHY are you making an API that takes such a pointer to an unknown type to begin with?

It's not unknown in any meaningful sense. It is known to be a sequence of 'arbitray' datums of a given length, which is the exact type of input required for the scenario given.

As the article explores, some argue that you should define that sequence with a concrete type, but the article states that it doesn't offer any additional value as is posits that void* already communicates the same. In other words, it suggests that void* is the concrete type for that type already.

Re: The beauty and simplicity of the good old C-style void* in C++

#117
post #106

The real question here is: WHY are you passing a blob of memory rather than a struct that uses the type system to describe and enforce what the contents are? I don't mean dressing up an anonymous pointer, which the author rightly complains about. I mean WHY are you making an API that takes such a pointer to an unknown type to begin with? Whenever you change the structure within that blob, your type checker won't flag…

I think the article names hashing as a use-case, which I can somewhat still agree. Operations that only depend on the bytes, I guess. But yeah, most things worth saying about this article have been said here already

Sure, if the function is expected to not treat the data as anything but bytes, then it might be acceptable in narrow circumstances.

But in such a case I'd argue FOR the ceremony, as a way of declaring from the API "The input is a sequence of bytes that I won't treat as anything other than a sequence of bytes", and declaring from each and every call site: "This is not a mistake; we really are 'converting' this struct to a series of bytes for this function to consume".

Then anyone auditing the code knows the intent by the shape of the types, and would quickly flag any typecasting shenanigans within the receiver function.

But even then, hashing a struct will rapidly bring you into the land of dragons and fairies. Abandon all hope if you have floats or UTF-8 (which have multiple representations for the same values).

Far better to remain type-aware if you value your sanity.

Re: The beauty and simplicity of the good old C-style void* in C++

#118
post #28

Earlier quoted context omitted.

It could have been there since the beginning, given that open arrays (aka spans) already existed in other languages, and there was even a failed proposal from Denis Ritchie regarding C. The C++ span proposal came from Microsoft, https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p01...

> already existed in other languages This argument is moot. The issue with spans is not that they require cutting edge technology to deliver. Before commenting, perhaps you should research why even Denis Ritchie himself could not sell his idea to C. It's funny how every single idea that's rejected is blindly lauded as brilliant but silenced due to some kind of conspiracy, and only the ideas that emerged are somehow b…

[deleted]

Re: The beauty and simplicity of the good old C-style void* in C++

#119
post #106

The real question here is: WHY are you passing a blob of memory rather than a struct that uses the type system to describe and enforce what the contents are? I don't mean dressing up an anonymous pointer, which the author rightly complains about. I mean WHY are you making an API that takes such a pointer to an unknown type to begin with? Whenever you change the structure within that blob, your type checker won't flag…

I think the article names hashing as a use-case, which I can somewhat still agree. Operations that only depend on the bytes, I guess. But yeah, most things worth saying about this article have been said here already

Hashing everything based on the byte representation breaks when you have a type where equality does not imply byte equality. Such as… floats (+0 and -0 are equal, but have different byte representation).

Re: The beauty and simplicity of the good old C-style void* in C++

#120
post #8

> Why should people complexify and uglify their C++ code with the uint8_t pointer (or std::byte), when void* works just fine?? Fair point (although to be honest: 'complexify' feels a bit of an exaggeration here to me), but the answer to this why is simple: document and express intent clearly. The compiler gave you an error first such that you're forced to consider what you're doing. Any seasoned C++ developer seeing…

Span will increase compilation time for no useful reason. It’s not any safer at the call site.

Span lets you use a ranged for loop to iterate over the contents without worrying about exceeding the bounds, which is safer than pointer+size if that's all you'll be doing. C++26 also introduces .at() for span, and the new hardened standard library enforces bounds checking when using operator [] on a span.
Post reply on HN