user77887: I'm trying to transfer data between a Arduino Uno board to a NodeMCU ESP8266 board, using nRF24L01+ transceivers module and RF24 library on both side. The data I'm transferring are stored in a struct defined this way:
// Struct declared in both code
struct sensorData {
    bool doorOpened;
    int light;
    int temperature;
    int humidity;
    float voltage_battery;
};
// Variable in Uno code (source node)
sensorData dataToSend;
// Variable in ESP8266 code (dest node)
sensorData dataToReceive;

But the data are not transferred properly between the two boards and I get random values or 0 when trying to display them from ESP8266 (values are correctly displayed from Uno).
Display in Uno (using signed short as data type, see following paragraphs):

Display in ESP8266 (using signed short as data type, see following paragraphs):

After some testing, I found out that memory-allocation on both boards are different, as Uno takes 2 bytes to store int while ESP8266 takes 4 bytes. Moreover, sensorData takes 11 bytes of memory on Uno (1 for bool, 2 for int and 4 for float, which sums up to 11 bytes), but takes 20 bytes of memory on ESP8266 (1 for bool, 4 for int and 4 for float, which does NOT sum up to 20 !).
Trying to solve this, I tried changing int for signed int, byte, short, signed short but the transmission problem remains. When using short or signed short (which takes 2 bytes on both boards), my structure sensorData still takes 11 bytes of memory on UNO while it takes 12 bytes of memory on ESP8266. For some reason, ESP8266 always takes more space than needed to store sensorData, probably causing bits to be wrongly placed when receiving data.
I'm sure that both boards, radio module and transmission protocol work as I successfully tested the same code with a smaller struct (text was "Hello World !" and cmp was increased at each transmission):
struct Package {
    char text[16];
    long cmp;
};

Does anyone have faced this issue before ? How could I solve that ?

user521: The esp8266 has a 32 bit mcu and the uno an 8 bit mcu so their variables have different storage requirements. You need to allow for this in your code.

user60516: For all the reasons mentioned in the other answers (different types sizes, alignment requirements and endianness), it's often a bad idea to use structs for data that needs to be sent/received (be it over the network or stored in files), as interoperability is often a problem.
Using a plain array of bytes (i.e. uint8_t[]) is often a much better solution, together with functions to read/write data with specific types at specific offsets.
In many higher-level languages (perl, php, python...) this is often done using pack/unpack or equivalents, but as far as I know there is no direct equivalent in C.
You then end up using temporary variables, htons/ntohs/htonl/ntohl and memcpy to copy data between the temporary variables and the transmit buffer. Floats are a bit more tricky because even though their format is well defined, they endianness is not, and may not be the same as integers, but htonf/ntohf are rare. In your case, I would recommend converting to integers with a factor of 10 (if you need one digit) or 100 (if you need 2) for instance.
If you're using C++ you could consider using Google's Protocol buffers

user4143: In addition to the rule of always using fixed and predictable sizes across different architectures, it's also a good idea to pack your structs. This prevents the compiler from padding smaller variables with blanks to align them with the architecture's word boundary when needed.  For example:
struct Package {
    uint8_t doorOpened;
    uint16_t light;
    int16_t temperature;
    uint8_t humidity;
    float voltage_battery;
} __attribute__((packed));

Depending on what "bytewise access" instructions are available on your target 32-bit architecture, without the packing you may end up with (worst case) the equivalent of:
struct Package {
    uint8_t doorOpened;
    // 3 bytes padding
    uint16_t light;
    // 2 bytes padding
    int16_t temperature;
    // 2 bytes padding
    uint8_t humidity;
    // 3 bytes padding
    float voltage_battery;
} __attribute__((packed));

Of course there may be a granular enough access method in the architecture which means the packing is irrelevant - but it's better to have it and it be ignored than to not have it and need it.

user68229: int, long, etc have different sizes depended on the compiler and target.
Use explicit sizes to make sure you're variables have the size you want. Eg. uint8_t, int16_t or int32_t, ... (as @Mat commented)
Also, I wouldn't use bool (if writing in C) as it's not really standard in C and the size is also implementation dependent: https://stackoverflow.com/questions/1608318/is-bool-a-native-c-type
Extra, there are different types of explicit sizes: https://stackoverflow.com/questions/5254051/the-difference-of-int8-t-int-least8-t-and-int-fast8-t
(but don't use it here otherwise you'll have again the same problem :))

user14301: There are three main issues you may need to deal with when passing structures between systems that use different processors.
The first is that data types vary in size between architectures. You can avoid this for integers by avoiding the basic C types and instead using the fixed size types from stdint.h/cstdint. For floating point types this is less of a problem as most systems use the IEEE single and double precision types for float and double.
The second is padding, according to the C standard padding is implementation dependent. In practice most compilers will insert the minimum amount of padding needed to meet alignment requirements. Exactly what the alignment requirements are also depend on the implementation, but the alignment requirement of a type is always a factor of it's size.
You can thus avoid compiler-generated padding on most architectures by designing your structure to place types on "natural" alignment (that is their offset in the structure is a multiple of their size) and to have a size that is a multiple of the largest type in the structure. So you might design your structure as.
struct sensorData {
    int8_t doorOpened; //size 1 offset 0
    int8_t spare; //size 1 offset 1
    int16_t light; //size 2 offset 2
    int16_t temperature; //size 2 offset 4
    int16_t humidity; // size 2 offset 6
    float voltage_battery; //size 4 offset 8
};

Another option is to use packed structures, but extreme care is needed when using such, especially in C++. It is easy to create unaligned pointers or references.
The final issue is byte order (also known as endian), if your systems use different byte orders for integer or floating point values you will need to insert conversions to deal with this.

77887: <p>I'm trying to transfer data between a Arduino Uno board to a NodeMCU ESP8266 board, using nRF24L01+ transceivers module and RF24 library on both side. The data I'm transferring are stored in a <code>struct</code> defined this way:</p>
<pre><code>// Struct declared in both code
struct sensorData {
    bool doorOpened;
    int light;
    int temperature;
    int humidity;
    float voltage_battery;
};
// Variable in Uno code (source node)
sensorData dataToSend;
// Variable in ESP8266 code (dest node)
sensorData dataToReceive;
</code></pre>
<p>But the data are not transferred properly between the two boards and I get random values or 0 when trying to display them from ESP8266 (values are correctly displayed from Uno).</p>
<p>Display in Uno (using <code>signed short</code> as data type, see following paragraphs):
<a href="https://i.stack.imgur.com/QaYxi.png" rel="noreferrer"><img src="https://i.stack.imgur.com/QaYxi.png" alt="Data displayed from Arduino UNO" /></a></p>
<p>Display in ESP8266 (using <code>signed short</code> as data type, see following paragraphs):
<a href="https://i.stack.imgur.com/V2eSd.png" rel="noreferrer"><img src="https://i.stack.imgur.com/V2eSd.png" alt="Data displayed from NodeMCU ESP8266" /></a></p>
<p>After some testing, I found out that memory-allocation on both boards are different, as Uno takes <em>2 bytes</em> to store <code>int</code> while ESP8266 takes <em>4 bytes</em>. Moreover, sensorData takes <em>11 bytes</em> of memory on Uno (1 for <code>bool</code>, 2 for <code>int</code> and 4 for <code>float</code>, which sums up to <em>11 bytes</em>), but takes <em>20 bytes</em> of memory on ESP8266 (1 for <code>bool</code>, 4 for <code>int</code> and 4 for <code>float</code>, which does NOT sum up to 20 !).</p>
<p>Trying to solve this, I tried changing <code>int</code> for <code>signed int</code>, <code>byte</code>, <code>short</code>, <code>signed short</code> but the transmission problem remains. When using <code>short</code> or <code>signed short</code> (which takes <em>2 bytes</em> on both boards), my structure <code>sensorData</code> still takes <em>11 bytes</em> of memory on UNO while it takes <em>12 bytes</em> of memory on ESP8266. For some reason, ESP8266 always takes more space than needed to store <code>sensorData</code>, probably causing bits to be wrongly placed when receiving data.</p>
<p>I'm sure that both boards, radio module and transmission protocol work as I successfully tested the same code with a smaller struct (<code>text</code> was &quot;Hello World !&quot; and <code>cmp</code> was increased at each transmission):</p>
<pre><code>struct Package {
    char text[16];
    long cmp;
};
</code></pre>
<p>Does anyone have faced this issue before ? How could I solve that ?</p>
 521: <p>The esp8266 has a 32 bit mcu and the uno an 8 bit mcu so their variables have different storage requirements. You need to allow for this in your code.</p>
 60516: <p>For all the reasons mentioned in the other answers (different types sizes, alignment requirements and endianness), it's often a bad idea to use structs for data that needs to be sent/received (be it over the network or stored in files), as interoperability is often a problem.</p>
<p>Using a plain array of bytes (i.e. uint8_t[]) is often a much better solution, together with functions to read/write data with specific types at specific offsets.</p>
<p>In many higher-level languages (perl, php, python...) this is often done using <code>pack</code>/<code>unpack</code> or equivalents, but as far as I know there is no direct equivalent in C.</p>
<p>You then end up using temporary variables, <a href="https://linux.die.net/man/3/htons" rel="nofollow noreferrer"><code>htons</code>/<code>ntohs</code>/<code>htonl</code>/<code>ntohl</code></a> and <code>memcpy</code> to copy data between the temporary variables and the transmit buffer. Floats are a bit more tricky because even though their format is well defined, they endianness is not, and may not be the same as integers, but <code>htonf</code>/<code>ntohf</code> are rare. In your case, I would recommend converting to integers with a factor of 10 (if you need one digit) or 100 (if you need 2) for instance.</p>
<p>If you're using C++ you could consider using Google's <a href="https://developers.google.com/protocol-buffers" rel="nofollow noreferrer">Protocol buffers</a></p>
 4143: <p>In addition to the rule of always using fixed and predictable sizes across different architectures, it's also a good idea to <em>pack</em> your structs. This prevents the compiler from padding smaller variables with blanks to align them with the architecture's word boundary when needed.  For example:</p>
<pre class="lang-cpp prettyprint-override"><code>struct Package {
    uint8_t doorOpened;
    uint16_t light;
    int16_t temperature;
    uint8_t humidity;
    float voltage_battery;
} __attribute__((packed));
</code></pre>
<p>Depending on what &quot;bytewise access&quot; instructions are available on your target 32-bit architecture, without the packing you may end up with (worst case) the equivalent of:</p>
<pre class="lang-cpp prettyprint-override"><code>struct Package {
    uint8_t doorOpened;
    // 3 bytes padding
    uint16_t light;
    // 2 bytes padding
    int16_t temperature;
    // 2 bytes padding
    uint8_t humidity;
    // 3 bytes padding
    float voltage_battery;
} __attribute__((packed));
</code></pre>
<p>Of course there may be a granular enough access method in the architecture which means the packing is irrelevant - but it's better to have it and it be ignored than to not have it and need it.</p>
 68229: <p><code>int</code>, <code>long</code>, etc have different sizes depended on the compiler and target.</p>
<p>Use explicit sizes to make sure you're variables have the size you want. Eg. <code>uint8_t</code>, <code>int16_t</code> or <code>int32_t</code>, ... (as @Mat commented)</p>
<p>Also, I wouldn't use <code>bool</code> (if writing in <code>C</code>) as it's not really standard in <code>C</code> and the size is also implementation dependent: <a href="https://stackoverflow.com/questions/1608318/is-bool-a-native-c-type">https://stackoverflow.com/questions/1608318/is-bool-a-native-c-type</a></p>
<p>Extra, there are different types of explicit sizes: <a href="https://stackoverflow.com/questions/5254051/the-difference-of-int8-t-int-least8-t-and-int-fast8-t">https://stackoverflow.com/questions/5254051/the-difference-of-int8-t-int-least8-t-and-int-fast8-t</a>
(but don't use it here otherwise you'll have again the same problem :))</p>
 14301: <p>There are three main issues you may need to deal with when passing structures between systems that use different processors.</p>
<p>The first is that data types vary in size between architectures. You can avoid this for integers by avoiding the basic C types and instead using the fixed size types from stdint.h/cstdint. For floating point types this is less of a problem as most systems use the IEEE single and double precision types for float and double.</p>
<p>The second is padding, according to the C standard padding is implementation dependent. In practice most compilers will insert the minimum amount of padding needed to meet alignment requirements. Exactly what the alignment requirements are also depend on the implementation, but the alignment requirement of a type is always a factor of it's size.</p>
<p>You can thus avoid compiler-generated padding on most architectures by designing your structure to place types on &quot;natural&quot; alignment (that is their offset in the structure is a multiple of their size) and to have a size that is a multiple of the largest type in the structure. So you might design your structure as.</p>
<pre><code>struct sensorData {
    int8_t doorOpened; //size 1 offset 0
    int8_t spare; //size 1 offset 1
    int16_t light; //size 2 offset 2
    int16_t temperature; //size 2 offset 4
    int16_t humidity; // size 2 offset 6
    float voltage_battery; //size 4 offset 8
};
</code></pre>
<p>Another option is to use packed structures, but extreme care is needed when using such, especially in C++. It is easy to create unaligned pointers or references.</p>
<p>The final issue is byte order (also known as endian), if your systems use different byte orders for integer or floating point values you will need to insert conversions to deal with this.</p>
