6 ms·
I actually like that C++ enforces a struct to be at least a byte long because it means you can have pointers to them and they will compare as non equal even if
by the_mitsuhiko 12y ago
I actually like that C++ enforces a struct to be at least a byte long because it means you can have pointers to them and they will compare as non equal even if you do not know the type. That is actually quite handy sometimes.
I wonder why Rust does not do that.
- pcwalton 12y agoC++ has a zero-sized type too: it's called "void". But it's not first-class, which is a weird restriction. Having first-class "void" is very useful. For example, you can make efficient hash sets out of hash maps by simply using () as the value.
- userbinator 12y agoHow would that be useful? If you need a hash set, use a hash set.
- pcwalton 12y agoFor the same reason any generic type is useful: you can use one implementation for multiple purposes (as a hash map implementation doubles as a perfectly good hash set implementation) without having to duplicate code.
- userbinator 12y agoI think that's backwards: a hash set implementation can be used as a hash map simply by storing objects whose comparison is limited to their key fields. A hash map with values that are all the same and never used just seems like a waste.
- pcwalton 12y agoIt's not a waste, because the fact that unit is zero-sized makes it boil away to nothing at runtime.
- malkia 12y agoI can have structs/classes that are zero sized, sometimes this is used for interfaces, or for "namespacing" as alternative to normal namespaces, or for functors, etc.
- AnimalMuppet 12y agoIIRC, C says that you get a real pointer back from malloc(0). Repeated calls return distinct pointers. For whatever that's worth...
- duaneb 12y agoAs someone who is pretty good at allocators, if you're calling `malloc(0)` you're wandering into very undefined territory. I've seen everything from valid allocations of non-zero length, whatever was on the stack, and just 0. The only real constraint is that free accepts the returned pointer.
- readerrrr 12y agoActually it is implementation defined. You may get a NULL pointer or a non-NULL pointer which may not be dereferenced. This is intentional so that you can always call free on a pointer received from malloc functions, regardless of the allocation result.( passing a NULL to free is ok )
- pbsd 12y agoNot exactly; from §7.20.3 in C99: If the size of the space requested is zero, the behavior is implementation- defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
- AnimalMuppet 12y agoAh, my error. But, quoting from my ancient copy of The C++ Programming Language, volume 2, §r5.3.3: "This implies that an operator new() can be called with the argument zero. In this case, a pointer to an object is returned. Repeated such calls return pointers to distinct objects." So my memory was from C++ new, not C malloc.
- mcguire 12y ago"or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object" I love the C standards. Is that defining the behavior of malloc or the behavior of the code calling malloc?
- eridius 12y agoBecause Rust doesn't let you compare references. Rather, comparing references actually compares the referred-to value (which requires that said value implements the comparison operators). What you can do is convert a reference into a raw C pointer `const T`, and then you can compare those addresses. But the reference type itself doesn't make any guarantees about the address, which means you can't make any assumption about the address of the resulting `const T`. Reference types only make guarantees about the semantics of the reference, and since you can't compare the pointer value of references, the pointer value is not something the reference type guarantees.