0

I have the following structure:

typedef struct LOG_EVENT
{
    time_t time;
    uint32_t count;
    int32_t error_type;
    uint16_t gm_state;
    uint8_t gm_mode;
    uint8_t mc_state;
} LOG_EVENT;

On 32-bit system , the structure's strict alignment is 4bytes so the members are aligned across 4-byte boundary. There is no padding added in this case because all members together are 4-byte aligned.

But this is not true on 64-bit system, where time_t is 64bit. The strict alignment in that case is 8-byte.

How can I change the alignment to 4-byte ? I want to align across 4-byte boundary on 64-bit system because I want to make sure no padding is done.

From the gcc attributes page https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html , it says that The aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well.

I don't see packed attribute taking in any arguments.

Also, if I use the byte-alignment like below, would it cause any issues compared to 4-byte alignment:

typedef struct __attribute__ ((packed)) LOG_EVENT
{
    time_t time;
    uint32_t count;
    int32_t error_type;
    uint16_t gm_state;
    uint8_t gm_mode;
    uint8_t mc_state;
} LOG_EVENT;
Monku
  • 2,440
  • 4
  • 33
  • 57
  • @yellowantphil I am not sure if that's a good idea. – Monku Mar 08 '17 at 00:49
  • 2
    "On 32-bit system , the structure's strict alignment is 4bytes" - Err.... no! There is no guarantee about alignment on any platform. But feel free to provide a reference to the standard stating different. That's an XY problem like your other question. **Why** do you want this alignment? It seems you should rethink your whole design. – too honest for this site Mar 08 '17 at 00:53
  • @Olaf I want 4-byte alignment because I don't want the compiler to add padding. If you look at the structure, considering strict alignment is 8-byte, 4bytes are added at the end. – Monku Mar 08 '17 at 00:57
  • @yellowantphil: That will not work, but potentially cause even more problems. – too honest for this site Mar 08 '17 at 00:57
  • Alignment is not related to padding. And that's not your actualy problem, but what you **think** is a solution. – too honest for this site Mar 08 '17 at 00:57
  • @Olaf Care to explain. – Monku Mar 08 '17 at 00:59
  • Possibly related question: http://stackoverflow.com/questions/3266766/field-alignment-of-a-struct-in-c-c (look at the 3rd answer). – DYZ Mar 08 '17 at 01:01
  • @Monku: Too broad. And I already stated this is an XY problem. – too honest for this site Mar 08 '17 at 01:07
  • If `time_t time;` needs 8-byte alignment, using code to force some sort of 4-byte alignment will certainly cause problems. – chux - Reinstate Monica Mar 08 '17 at 01:07
  • @DYZ: That's a different question. But both are most likely the wrong way for a specific problem. TRoo bad we don't know the problem because both askers don't tell us. – too honest for this site Mar 08 '17 at 01:09
  • 2
    What @chux said: Best case scenario, aligning eight byte `time_t` to four byte boundary will make your code run slower (forgiving architectures won't die, but unaligned access still costs). Worst case, unaligned access causes the code to crash. Which means it's definitionally non-portable. Saving four bytes out of 24 (when memory is cheap) in exchange for breaking portability and running slower even where it works is not a good trade-off. – ShadowRanger Mar 08 '17 at 01:11
  • 1
    Useful link [Is gcc's __attribute__((packed)) / #pragma pack unsafe?](http://stackoverflow.com/q/8568432/2410359) – chux - Reinstate Monica Mar 08 '17 at 01:18

2 Answers2

1

#pragma pack(4) will set alignment to 4 bytes.

Notice this directive is not part of the standard, this was originally introduced in MSVC and later adopted by gcc for compatibility with the Microsoft's compiler.

Also, notice the size of types like time_t, size_t and all pointer types will vary between those architectures. If your intention is to make a structure that is intelligible between applications running on those two architectures this will be a problem.

Also know that there is no benefit in using 64-bit applications other than the fact that you can address more than 4GB of memory, if you don't need all that memory you can stick to 32-bit, there is no sin in that.

Havenard
  • 27,022
  • 5
  • 36
  • 62
  • *Also know that there is no benefit in using 64-bit applications* Not true. On x86 systems, the number of general-purpose registers doubles from 8 to 16. SSE registers are also doubled. – Andrew Henle Jan 13 '20 at 13:58
  • @AndrewHenle That's true, but from what I've read this basically just mitigates the fact that you're using significantly more L2 space and the longer instructions take more memory bandwidth and so on, I don't know if this notion is outdated with current CPUs, but the consensus at the time was that 64-bit applications were, although marginally, in fact slower. This may have changed, but I'm not the person to ask. Not that it matters since like it or not 32-bit on PC is eventually going to die. – Havenard Jan 13 '20 at 20:03
0

The most straightforward thing to do is ... not use time_t. Use fixed-width types only.

typedef struct LOG_EVENT
{
    int32_t time;
    uint32_t count;
    int32_t error_type;
    uint16_t gm_state;
    uint8_t gm_mode;
    uint8_t mc_state;
} LOG_EVENT;

You give up the ability to handle timestamps outside the range of signed 32-bit time_t (usually, but not always, 1901-12-13T20:45:52Z through 2038-01-19T03:14:07Z) but if you're trying to work with an on-disk record array with 32-bit timestamps, which is the most plausible explanation here, that's not an issue.

zwol
  • 135,547
  • 38
  • 252
  • 361