This sounds straightforward enough, but I'm struggling to find a good answer.
Suppose I declare a C++ class with private members that collectively occupy an odd number of bytes. Say...
class Foo {
private:
uint8_t bitflags;
uint32_t millis;
}
or
class Foo {
private:
uint8_t rawData[3];
}
If I compile it using GCC or Clang (possibly, wrapped inside the Arduino IDE, or multiply-wrapped inside PlatformIO, CMake, and an IDE like CLion), is there any likely scenario where the compiler (when targeting 8-bit AVR... specifically, the ATmega2560 on an Arduino Mega2560) would be inclined to add padding bytes to the portion of the class stored in SRAM? Say... between bitflags
and millis
, or between an instance of Foo
and a uint64_t
right after it?
If yes, what do I need to use to tell the compiler, "absolutely, positively DO NOT pad variables in SRAM (and, if you find yourself in a situation where it's seemingly unavoidable, at least output a prominent compile-time warning, if not an outright compilation-stopping error)?
Then... if I do that... are there any negative consequences to doing that with code that's targeting (and ultimately running upon) an 8-bit AVR?
As far as I know, 8-bit AVR has never had specific opcodes for copying a pair of consecutive bytes between registers and SRAM (I think, because Atmel literally ran out of opcode mapping space, and had nowhere to put hypothetical new opcodes like, "ldw rz, $f00d"), and movw
only applied to pairs of registers... so, in theory, there's no reason for the compiler to "optimize" SRAM access to be word-aligned.
That said... I suppose it's not inconceivable that a compiler might default to word-alignment (even on platforms where it doesn't matter), just for the sake of ABI consistency between different platforms.
Before someone suggests, "try it and see!"... I've gotten far enough into learning C++ to know that with C++, you can't trust "compiles without errors and passes unit tests on my computer, with {this} IDE" as a general-purpose proof-of-correctness for C++ involving "implementation-defined" or "undefined" behavior. AFAIK, padding behavior is "implementation-defined".
MOVW
are always aligned in the sense that they're even:odd pairs (which also become aligned in the memory mapped register file (when it is mapped). That said, it doesn't appear (from tests) that they did this, probably because it wasn't worth bloating structures that may not ever be optimized withMOVW
usages. I have no idea what sort of answer would satisfy this question.__attribute__ ((__packed__))
or the#pragma
or C++ attribute way (way; it's still non-standard) of specifying it, but really I don't know. I expect this attribute does nothing in avr-gcc because it would seem to be the normal behaviour in that compiler under common options anyway. But again... I don't know.