Re: memcpy
Christopher Pisz <nospam@notanaddress.com> writes:
On 2/6/2015 10:56 AM, Scott Lurndal wrote:
Christopher Pisz <nospam@notanaddress.com> writes:
On 2/5/2015 7:32 PM, Ian Collins wrote:
Christopher Pisz wrote:
There has to be a boundary somewhere. I already asked Ian, but I'll ask
again. What are you going to do at that boundary? What is someone else
going to do?
I already answered - the platform library interfaces use fixed width and
other typedef types. System data structures use fixed width types. The
standard library uses typedef types.
Ok, if I understand you correctly, then you are using these fixed width
types in code that the operating system calls. You are leaving it to the
operating system to deal with it. On the other side of the operating
system, I am calling libraries that, in turn, call the operating system,
and I am using int rather than int32_t justifiably. Is that correct?
It's really simple. Use the defined interface type. If the library
routine header file requires an int, pass an int. If it requires an
unsigned long long, pass an unsigned long long. If it requires an
uint8_t, pass a uint8_t.
Ok, so back to where we were from the start. If I never have a
dependency that uses these types, then I should never use them, in your
opinion.
That's not what I said. I simply said that you want to match
the argument types to public API's. For usage within the application,
use the appropriate type for the domain of the data.
The C++ code I'm currently working on has a lot of this:
union GICD_IIDR_t
{
uint32_t u;
struct
{
#if __BYTE_ORDER == __BIG_ENDIAN
uint32_t productid : 8;
uint32_t reserved_20_23 : 4;
uint32_t variant : 4;
uint32_t revision : 4;
uint32_t implementer : 12;
#else
uint32_t implementer : 12;
uint32_t revision : 4;
uint32_t variant : 4;
uint32_t reserved_20_23 : 4;
uint32_t productid : 8;
#endif
} s;
GICD_IIDR_t() { u = 0xa100034c; }
GICD_IIDR_t(uint32_t data) { u = data; }
GICD_IIDR_t& operator=(uint32_t data) { u = data; return *this; }
};
As this is matching the definition of a hardware (MMIO) register,
the fundamental type is important, particularly since the application
is built for both 32 and 64-bit hosts (as well as both big and
little-endian machines). It's never passed to a library function.
As there are many 64-bit registers defined, it's important not to use
a type that changes based on the target architecture.
In many other places, a core number is passed as a parameter. The
domain of the problem restricts the core number to a +ve value less than
2**32, so a uint32_t is an appropriate type for the typedef 'corenum_t',
where 'int' would be completely inappropriate (a negative core number
is a meaningless concept).