<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: using sizeof with a struct, strange behavior?</title>
		<link>http://forums.leaflabs.com/topic.php?id=1319</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:24:12 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=1319" rel="self" type="application/rss+xml" />

		<item>
			<title>gbulmer on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8121</link>
			<pubDate>Wed, 08 Feb 2012 05:45:40 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">8121@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;&#38;lt;&#38;gt;... is it really elegant and simple?&#38;lt;/&#38;gt;&#60;br /&#62;
My favourite Einstein quote is &#60;a href=&#34;http://www.alberteinsteinsite.com/quotes/einsteinquotes.html&#34;&#62;&#34;Everything should be as simple as possible, but not simpler.&#34;&#60;/a&#62;&#60;br /&#62;
IMHO the problem with packing the struct and memcpy (or the for loop) at both ends of a communication is it relies on fragile underlying assumptions about two compilers, two runtime systems, two processors, and how the two programs might evolve.&#60;/p&#62;
&#60;p&#62;If this is likely to last for some time, then it might be worth taking steps to check that both programs match. Maybe exchange a 'version number' as part of the communication so something can check that the protocol is understood and common.&#60;/p&#62;
&#60;p&#62;I wrote code to read &#38;amp; write binary files created using this &#34;packed structure&#34; technique in the '80s. It was converting between a well defined CAD file format and a proprietary binary format used by a Pascal program. Unpleasant.&#60;/p&#62;
&#60;p&#62;With judicious use of macros and include, and avoiding unique constructs, I think it *might* be possible to use the same code on the Maple and C#. If there will very likely be a real problem keeping the code on both sides of the communication compatible, I'd be tempted to write two sets of macro definitions, and generate the code from a common source.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>djk on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8116</link>
			<pubDate>Tue, 07 Feb 2012 21:42:51 +0000</pubDate>
			<dc:creator>djk</dc:creator>
			<guid isPermaLink="false">8116@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;All noted thanks! &#60;/p&#62;
&#60;p&#62;FYI - DIY packing it as you suggested seems to work well as &#34;struct __attribute__ ((__packed__))&#34; seems to test OK. Is it the most efficient (size, speed) for this target? is it most portable for the future? is it really elegant and simple?....well all are separate questions to be asked and answered based upon what the goal and i need to re-visit this.&#60;/p&#62;
&#60;p&#62;BTW - in my case the host at the moment is C# so is it really a mirror? well sort of, in the way a circus mirror is technically a mirror.&#60;/p&#62;
&#60;p&#62;Very much appreciated.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8103</link>
			<pubDate>Mon, 06 Feb 2012 19:58:29 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">8103@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;It is probably worth adding for anyone reading this thread, that the overhead of doing the calls to the pack functions would be minimal if they were &#60;code&#62;static inline&#60;/code&#62;, e.g. before they are used:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;static inline uint8_t* pack_uint8_t(uint8_t* dest, const uint8_t value) {
    dest[0] = value;
    return dest + sizeof(value);
}

static inline uint8_t* pack_uint16_t(uint8_t* dest, const uint16_t value) {
    uint8_t* valueptr = (uint8_t*)&#38;amp;value;
    if (isSameEdian) {
        dest[0] = valueptr[0];      // Warning: preserves endian
        dest[1] = valueptr[1];      // Warning: preserves endian
    } else {
        dest[0] = valueptr[1];      // Warning: CHANGES endian
        dest[1] = valueptr[0];      // Warning: CHANGES endian
    }
    return dest+ sizeof(value);
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;That would remove function call overhead.&#60;/p&#62;
&#60;p&#62;As the value of &#60;code&#62;isSameEdian&#60;/code&#62; is constant, a c++ compiler should remove the if test. So it likely compiles to byte copies. It might actually generate smarter code. So it should be comparable to the &#60;code&#62;for&#60;/code&#62; loop.&#60;/p&#62;
&#60;p&#62;It also has the benefit of its effect being a bit more explicit and predictable. &#60;/p&#62;
&#60;p&#62;Finally, the code on the host could be a mirror image, so not too hard to maintain. Even if extra fields are inserted into the structs on the host or Maple; the host and Maple structs wouldn't need to be in the same order or have all of the same fields, the communication order is in the code.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8100</link>
			<pubDate>Mon, 06 Feb 2012 19:18:34 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">8100@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;djk - you could pack the data if you really want to.&#60;br /&#62;
You could try putting the UINT8 after the UINT16's. &#60;/p&#62;
&#60;p&#62;I have not checked this, so I am guessing, but &#60;code&#62;command&#60;/code&#62;, the second UINT16, would cross a word, 4 byte, boundary. So it take two cycles to access memory, instead of one, so I'd hope the compiler tries to ensure things are quick (and predictable) with the compiler flags that Maple IDE applies. &#60;/p&#62;
&#60;p&#62;Also, I believe &#34;bit band&#34; addressing only works for aligned addresses. So it would be a handy if the compiler tried to ensure things are aligned by default.&#60;/p&#62;
&#60;p&#62;If things were exactly laid out the way they are needed, consider using &#60;code&#62;memcpy&#60;/code&#62; instead of the &#60;code&#62;for&#60;/code&#62; loop:&#60;br /&#62;
&#60;code&#62;memcpy(dest, &#38;amp;tester, sizeof(tester);&#60;/code&#62;&#60;br /&#62;
I think gcc might 'inline' it. For 5 bytes it might not matter, but for larger chunks of memory, I vaguley remember gcc does some quite sneaky things.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>djk on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8094</link>
			<pubDate>Mon, 06 Feb 2012 14:19:58 +0000</pubDate>
			<dc:creator>djk</dc:creator>
			<guid isPermaLink="false">8094@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Thank you both very very much!&#60;/p&#62;
&#60;p&#62;something elegant and simple about:&#60;/p&#62;
&#60;p&#62;for(i=0; i&#38;lt;sizeof(tester) i++)&#60;br /&#62;
{&#60;br /&#62;
 *src++ = *dest++;&#60;br /&#62;
}&#60;/p&#62;
&#60;p&#62;and being done with it! ah wishful thinking i guess. &#60;/p&#62;
&#60;p&#62;I'm aware of the endianess issues on the host side and was going to sort that bit and individual parsing there (it's headed for windows) i guess for some reason i didnt expect the packing if the M3 can handle bytewise alignment (or maybe i've been using 8 bit micro's a bit much lately).&#60;/p&#62;
&#60;p&#62;Also i'm building a multi-layer protocol and what i left out of my struct above was a payload byte array and a checksum byte. So i've got another protocol layer to set on top of the payload array that will have to deal with struct packing issues as well. At least now i know what to expect and how to respond.&#60;/p&#62;
&#60;p&#62;Again greatly appreciated!
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8072</link>
			<pubDate>Sun, 05 Feb 2012 07:42:20 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">8072@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;djk - In general different processors can (and do) represent the same data types in different ways. Then different compilers, or different compiler settings, can pack data in different ways. Network protocols, like TCP/IP have to solve this problem.&#60;/p&#62;
&#60;p&#62;The first variation is ARM processors can store multi-byte numbers in a different byte order to the way x86 and x86-64 store multi-byte numbers.&#60;br /&#62;
Another variation is a compiler for the same architecture might pack data with some compiler options, and not pack the data in the same way with different compiler options.&#60;/p&#62;
&#60;p&#62;As jcsalomon wrote don't try to send a struct in one chunk.&#60;/p&#62;
&#60;p&#62;So, to make a binary data stream to be predictable, copy the data to a byte buffer.&#60;br /&#62;
That will ensure that code, that you control, lays the data out and you can remove dependencies on the compiler and processor.&#60;br /&#62;
For example, the host processor might store a multi-byte number (e.g. UINT16) with the 'high' part of the number in the byte with a high address, while the Maple might store it in the byte with the low address.&#60;/p&#62;
&#60;p&#62;So, you might code it as (written on Mac, haven't got Maple next to me):&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;#include &#38;lt;stdio.h&#38;gt;
#include &#38;lt;stdint.h&#38;gt;

/** packing functions
 */
const int isSameEdian = 1;        // Preserve endian of numbers

uint8_t* pack_uint8_t(uint8_t* dest, const uint8_t value);
uint8_t* pack_uint16_t(uint8_t* dest, const uint16_t value);

struct Tester
{
    uint8_t header;
    uint16_t packetType;
    uint16_t command;
} tester = { &#38;#39;c&#38;#39;, 0x00ff, 1234 };

int main (int argc, const char * argv[]) {
    uint8_t buff[sizeof(tester)];
    uint8_t* buffptr = &#38;amp;buff[0];

    buffptr = pack_uint8_t(buffptr, tester.header);
    buffptr = pack_uint16_t(buffptr, tester.packetType);
    buffptr = pack_uint16_t(buffptr, tester.command);

    printf(&#38;quot;Size=%d\n&#38;quot;, buffptr-buff);
    for (int i=0; i&#38;lt;buffptr-buff; ++i) {
        printf(&#38;quot;%#4x &#38;quot;, buff[i]);
    }
    printf(&#38;quot;\n&#38;quot;);
    return 0;
}

uint8_t* pack_uint8_t(uint8_t* dest, const uint8_t value) {
    dest[0] = value;
    return dest + sizeof(value);
}

uint8_t* pack_uint16_t(uint8_t* dest, const uint16_t value) {
    uint8_t* valueptr = (uint8_t*)&#38;amp;value;
    if (isSameEdian) {
        dest[0] = valueptr[0];      // Warning: preserves endian
        dest[1] = valueptr[1];      // Warning: preserves endian
    } else {
        dest[0] = valueptr[1];      // Warning: CHANGES endian
        dest[1] = valueptr[0];      // Warning: CHANGES endian
    }
    return dest+ sizeof(value);
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This example gives a mechanism to guarantee the packing and byte order independent of the underlying processor or compiler.&#60;/p&#62;
&#60;p&#62;Change &#60;code&#62;isSameEdian&#60;/code&#62; to &#60;code&#62;isSameEdian = 0&#60;/code&#62; and you'll get the other byte ordering for multi-byte numbers.&#60;/p&#62;
&#60;p&#62;It happens that ARM Cortex-M3 can handle misaligned numbers, but other members of the ARM family, and some other processors can not handle misaligned numbers. Hence IMHO it is better to avoid relying on a particular processor+compiler+compiler-settings properties. (Code tends to get reused.)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>jcsalomon on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8069</link>
			<pubDate>Sun, 05 Feb 2012 03:56:42 +0000</pubDate>
			<dc:creator>jcsalomon</dc:creator>
			<guid isPermaLink="false">8069@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;You might try&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;
&#60;code&#62;struct  __attribute__ ((__packed__)) tester {…};&#60;/code&#62;
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;but if the padding is there for a good reason, access to the mis-aligned members might be slow or cause a trap.&#60;/p&#62;
&#60;p&#62;A better solution is not to try sending the whole struct over the wire at once, but field-by-field — and if the machine at the other end isn't guaranteed to be the same model, make sure to send things in a well-defined byte order.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>djk on "using sizeof with a struct, strange behavior?"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1319#post-8065</link>
			<pubDate>Sat, 04 Feb 2012 22:50:26 +0000</pubDate>
			<dc:creator>djk</dc:creator>
			<guid isPermaLink="false">8065@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;i'm having unexpected results using sizeof when trying to get the size of a struct in bytes when that struct contains multiple data types. &#60;/p&#62;
&#60;p&#62;Example:&#60;/p&#62;
&#60;p&#62;struct tester&#60;br /&#62;
{&#60;br /&#62;
UINT8    header;&#60;br /&#62;
UINT16   packetType;&#60;br /&#62;
UINT16   command;&#60;br /&#62;
};&#60;/p&#62;
&#60;p&#62;doing a println(sizeof(tester),DEC); to the serial monitor returns 6! &#60;/p&#62;
&#60;p&#62;I expect this to be 5? It appears there is a byte getting stuffed between UINT8 and UINT16. &#60;/p&#62;
&#60;p&#62;Does this have to do with storage boundaries on the STM32? because we are dealing with 32bit words?&#60;/p&#62;
&#60;p&#62;This causing a problem doing a pointer and bytewise copy (binary serial payload) on a serial stream of binary data i'm working with.&#60;/p&#62;
&#60;p&#62;suggestions and feedback greatly appreciated!
&#60;/p&#62;</description>
		</item>

	</channel>
</rss>
