Re: ill-formed reference to pointer
On Jan 30, 2:20 am, Ian Collins <ian-n...@hotmail.com> wrote:
On 01/30/11 06:58 PM, m0shbear wrote:
On Jan 30, 12:38 am, Ian Collins<ian-n...@hotmail.com> wrote:
On 01/30/11 06:03 PM, m0shbear wrote:
typedef uint8_t u8;
typedef uint64_t u64be;
These are horrible!
I use the 'be' suffix to note that the variable is explictly big-
endian instead of native-endian. Why is that bad?
I guess that's OK, but the typedef doesn't give you any protection form
mixing u64be and uint64_t types.
It's like a #define which evaluates to nothing - it serves more as a
pre-/post-condition note than a compiler verifiable pre-/post-
condition.
template<typename T>
struct itype {
typedef T value;
typedef T& reference;
typedef T const& const_reference;
typedef T* pointer;
typedef T const* const_pointer;
};
#define PTR_CAST(T, p) (reinterpret_cast<T*>(p))
Why do this?
Long symbol names become annoying to read, and reinterpret_cast is
used enough that creating a wrapper macro for it is clearer.
Using reinterpret_cast anything other than infrequently should set alarm
bells wringing.
It's only in the bitwise portion of the inner loop. It was faster to
macro it and I was too lazy to regex it via s/Ptr_cast<([a-z0-9_]+ ?
const?)>/reinterpret_cast<\1>/g.
#define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
const,src); (src) += 8
The macro I'm trying to convert into an inline function.
What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
bytes, to minimize the amount of instructions generated. And the C++
version of the C-style cast maps to reinterpret_cast.
Why don't you just write
template <typename S, typename D>
void xf64( S* dst, const D* src )
{
*reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
uint64_t*>(src);
src += 8;
}
Which is closer to your macro?
Nope: src will be unchanged since it's copied by value instead of by
reference.
In the macro, the ability to assume that the src token is a reference
is a precondition.
In any case, the function's arguments are (uint8_t *, const uint8_t
*), so it works. I was just playing around with constness and
references and got bit.
It either case, things could turn nasty if the pointers aren't correctly
aligned for uint64_t.
Indeed, which is why I'm making a padding wrapper for unaligned xor,
one of the reasons being the ability to add simd intrinsics at a later
time. Not all cpus support unaligned 64/128-bit load-store between mem
and simd reg(s).
Now why does the compiler auto-constify any non-const pointer used as
the second argument in memcpy() but refuses to do so here?
Because the parameter is a reference.
References do a damn good job of killing off C tricks I've learned
over the years :P