We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
This seem just dummy question.
What is a problem. I have some old project, that works on 8 bit prosecos. Now I reforming for arm7 procesor.
Ok, I find out, that in old procesor is int 16 bit type, in arm is 32 bit type, no problem. In rtl.h are definitions like U32 as unsigned int, ... and on the and U8 as unsigned char. Sizeof(U8) is 1 - 1 byte (8 bit).
Than i define my own structure for exaple:
typedef struct { U8 byte_1; U16 bytes_2; } MY_STRUCTURE;
sizeof(MY_STRUCTURE) is 4!!! How could be this posible?
Alignment. The U16 member is 16-bits wide, and so has to start on an even address. Because of this, the compiler has to add a hidden pad byte between byte_1 and bytes_2.
Most modern microprocessors requires data to be aligned. Some because of the increased speed of getting the data when it is aligned, allowing access with a single memory read, and some because the hardware is totally
unable to process unaligned integers (other than possibly emulated in an exception handler).
32-bit processors normally want their 16-bit variables on an even address, and their 32-bit or larger variables to be 4-byte aligned, i.e. have an address with the last two bits zero. Some processors wants (or requires) 64-bit integers, doubles etc to be 8-byte aligned.
Besides the width of the memory bus, most modern processors also makes use of a processor cache, and the cache is normally way wider than the memory interface, so a cache word may contain two, four or more memory words.
Thanke you for your quick reply.
... soo, the sizeof will not work, or can be sizeof somehow change? someone write own code like sizeof that works in this case?
sizeof() will return the true size. It has to include the padding byte because the padding does consume space.
"the sizeof will not work"
Yes, sizeof will work precisely as defined!
The key is a correct understanding of how sizeof works!
A decent 'C' textbook should explain this; See also: c-faq.com/.../endpad.html
" in old procesor is int 16 bit "
To be precise, this is defined by the compiler, not the processor.
The compiler writers could have decided to make their 'int' 24 or 32 bits - or anything else that took their fancy!
That would, of course, have been a very unusual - even bizarre - decision; but they might have had their reasons, and there's nothing to stop them...!
IBM has an old system with 36-bit integers :)
This results in a char either having 7 or 9 bits, depending on if the compiler fints 4 or 5 characters into an int.
I tried like I seid, sizeof(MY_STRUCTURE), but didne't work. I get value 4 not 3! Tested again. This is not such big problem, real problem is that I read data from SD card, for example 3 bytes, but I can't use memcpy(&my_structure, &readed_data[0], 3).
My real structures are 190 bytes big, have 20 subvariables.
Now I using just dummy way. Copy to buffer, than copy to my structure, subvariable by subvariable
Your structure really is 4 bytes, so sizeof(x) should return 4. Four of your structures will consume 16 bytes, so if you copy 16 bytes from the memory card into an array of structures, all data will be completely messed up. You will take 5 1/3 structures from the memory card and copy into 4 structures in the ARM memory...
You are now learning that you should never use memcopy to import/export data between different systems. The only portable way is to read the data from the memory card as an array of bytes, and then explode the data into structures, field by field.
In some situations, you may use a packed structure - i.e. requesting that the compiler should ignore data align and store the information without internal padding. The problem with packed data is that the processor has to take extra steps whenever it is processing the misaligned fields. The compiler may generate code that read your 16-bit variable as two 8-bit values and then have one of the bytes left-shifted 8 bits and combined with the other byte. That hurts both code size and speed.
Even if you use packed arrays, you have to take byte order into consideration. Is the external data stored with least and most significant byte of multi-byte integers placed in the same order as your processor needs? If not, then you must either byte-swap all multi-byte fields in the struct after read or before write, or you must write your own code to pack/unpack from a byte array.
You can see the effect of the alignment padding byte by adding a second byte, e.g.
typedef struct { U8 byte_1; U8 byte_2; U16 bytes_2; } MY_NEW_STRUCTURE;
sizeof(MY_NEW_STRUCTURE) may now be 4, or it may be 6! It's one of those C compiler implementation things you just need to learn about.
"Is the external data stored with least and most significant byte of multi-byte integers placed in the same order as your processor needs? If not, then you must either byte-swap all multi-byte fields in the struct after read or before write, or you must write your own code to pack/unpack from a byte array."
I did like you said.
part of code:
data->ip_1 = MK_U32_FROM8S(buf[counter], buf[counter+1], buf[counter+2], buf[counter+3]); #define MK_U32_FROM8S(high8,med_high8,med_low8,low8) \ MK_U32(MK_U16(high8,med_high8), MK_U16(med_low8, low8)) #define MK_U32(high16,low16) \ ((U32)( ((U32)(high16) << 16) | (U32)(low16) )) #define MK_U16(high8,low8) \ ((U16)( ((U16)(high8) << 8) | (U16)(low8) ))
This way I'm realy sure, that I get regular value.
Thanks four yours explanations, I learned o lot of new and useful things.
Peter