This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

wrong evaluation of the compiler??... Very rare error

Dear all,

I have this ultra simple strcture

typedef struct
{ uint8_t Hora; uint16_t Data1;
} EEpromPaqueteDatosS;

When I do sizeof(EEpromPaqueteDatosS) it returns 4!!! But if I do the sizeof of the same structure with only one variable, in other words, with uint8_t variable it returns 1 and with uint16_t it returns 2.. but if the structure have the two variables it returns 4!!

Also if I copy the structure to a uint8_t vector I can found a strange byte in the middle.. like this:

EEpromPaqueteDatosS EEpromPaqueteDatos;
uint8 data[4];

EEpromPaqueteDatos.Hora = 0x10;
EEpromPaqueteDatos.Data1= 0x1020;

When I copy the structure to data, data is like 0x10, 0x??, 0x20, 0x10.. why this extra byte!!!!

Can anybody help me with this???

Thanks

  • Been There. Done That.

    It might seem like a good idea to try to match your comms protocol packets to packed 'C' structures like this - but it can, indeed, end up as more trouble than it's worth.

    Bet to create functions to "serialise" and "de-serialise" your data: en.wikipedia.org/.../Serialization

    www.lmgtfy.com

  • I never pack a structure intended for the cable or similar. Always an encode/decode or pack/unpack or serialize/unserialize explicitly implemented. It is 100% visible what happens, so you don't need to wonder when debugging. And the code can be moved to another processor with different byte order and the pack/unpack will still do as intended. So less code to rewrite when supporting multiple architectures.

  • Hi,

    Hans, you are right, but, don't think my phrase was as bad as you said.. but, I will try to ask the questions better.

    By the other hand memory is not important today, but, in some cases 3 or 4 more bytes when all data is 10 bytes in cost sensitive applications can be a problem.

    Thanks.

  • "By the other hand memory is not important today, but, in some cases 3 or 4 more bytes when all data is 10 bytes in cost sensitive applications can be a problem."

    You are not likely to find a chip with only 10 bytes of data, so you will then not get 30% or 40% of filler bytes. So a single struct can be used without pack.

    And if you need to store 1000 structures, you have enough that it is meaningful to see it as a database and create a "read_record()" and "wrtie_record()" that handles pack/unpack.

  • Hi,

    When you have to store 10 bytes every 1 hour and the program must write data for some month, 3 or 4 bytes is very important, is the difference berween store 40 days or 70 days using a memory lime M24C128... You can place a larger memory or two memories, but, when is a cost sensitive application, you cant...

  • In that case, as already discussed, you should not be writing structures - you should have read() and write() functions to access the storage as a "stream"...

  • If I write a data logger, where memory is important, I would probably even check if I need 8 + 16 bits or maybe just 5 + 12 bits.

    I might even, depending on type of sample, see if I can have one bit of data represent if following record is having absolute or relative values. Storing temperatures as deltas can save a lot of memory space.

    But trying to use raw C structs for binary storage on a memory media is just plain silly. It's a great example of walking the wrong path. Especially so if that memory is removeable and should potentially be read by another device.

    The language don't have a standard for packing structures just because it isn't a good way to solve the kind of problem you are trying to solve.

    Time to take two steps back and switch to a real solution. A solution that is not depending on compiler flags, pragmas or other tricks.

  • By the way - your 8-bit value is named "Hora". That would be "hour". If your logger do record one sample every hour, you don't have a need to store any hour value in the sample. So 3 bytes suddenly became 2 bytes. And if the 16-bit value can never be larger than what fits in 15 bits, you could use one bit as "flag" to store a hour jump in case the device has been turned off and there is a jump in hours since previous sample recorded.

    In the end, your packed data would probably waste a lot of memory, if memory really are important.

  • This was an example to solve the problem, in my case the sturcture is more complex and hard to explain... Is curious that the people try to say absolute solutions without knowing at all the question like use "write" o r "read" like stream or other "solutions" posted here without know other things related to the device or its operation... The problem is solved and this discusion have no sense now, anyway, thaks.

  • If the linker happen to be at an odd address when it link the struct no packing will happen, if it is at an even address there will be a packbyte inserted between the two.

    No, it won't. It's forbidden by the language definition.

    well, if so Keil (recent version) breaks the "language definition"

    I caught this as a bug, and fixed it instead oof complaining to Keil.

    I do not know the "language definition" but the case in point was a const struct for the defaults and a struct for the initialized values. copying the defaults into the variable struct blew the thing.

    Erik

  • had I started this from scratch I would have created the struct the way i have done ever sice my first exposure to an "alignment critical" processor

    I always make structs this way:
    dwords
    words
    bytes

    that way there never is an alignment issue

    Erik

  • Since you didn't give any of those details, how could anyone else know them?!

    Therefore, we discuss general principles - that can be applied in all cases.

    "this discusion have no sense now"

    Note that this is not a free consultancy service - it is an open discussion forum.

    It seems that there are still issues worthy of discussion - even if not specifically pertinent to your particular application at this time.

  • "I do not know the "language definition" but the case in point was a const struct for the defaults and a struct for the initialized values. copying the defaults into the variable struct blew the thing."

    Post the code sequence, and we may be able to come up with a reason for the problem.

  • "Is curious that the people try to say absolute solutions without knowing at all the question like use "write" o r "read" like stream or other "solutions" posted here without know other things related to the device or its operation.."

    It is "curious" that the compiler must implement code to serialize read and write if you play with a packed structure. Which is a reason why the general recommendation is to not use a compiler-specific attribute to hide an issue in a way that fools other developers and can result in huge problems with concurrency etc.

    It is "curious" that the normal solution is to explicitly call code that does the pack/unpack, where what happens is visible and can be debugged or potentially optimized depending on the specific needs.

    That you did write the answer you did, indicates that you did not spend some time really thinking through the answers you have received. If you had, and didn't agree with some of it, you would have posted specific follow-up questions or "wouldn't this ..." comments instead.

    Well, you are free to run into walls if that makes you happy. We don't care if you use problematic structures. We can suggest reasons to avoid doing it, but it is still up to you to ignore recommendations if you think maybe 3-digit years of experience isn't relevant.

  • Is curious that the people try to say absolute solutions without knowing at all the question like use "write" o r "read" like stream or other "solutions" posted here without know other things related to the device or its operation..

    the usual reason for this is that the question was formulated in a vague way

    Erik