Prev: 50 ohm PCB antenna track impedance
Next: BT earpieces
From: ChrisQ on 10 May 2010 10:47 Hans-Bernhard Bröker wrote: > ChrisQ wrote: > > > It formalizes an association between two things one of which serves > no actual purpose at all. I doesn't gain you anything on the one > association that actually needs to be established in this context: > that between the struct itself and sizeof(struct). You'll end up > writing > > fwrite(&u.array, 1, sizeof(u.array), fp); > > when you could have written > > fwrite(&s, 1, sizeof(s), fp); > > instead. And you really think _that_ is an improvement? Perhaps not a good example. I would do: vFormatSave (&struct); With the structure defined in the associated module header file, hiding all the format conversion away from the functions that use and save it. ie: separate form and function. There would be an abstraction layer under that as well, to factor out any hardware specific stuff. Many (most ?) self contained embedded systems don't need this consistency, but would still encapsulate the conversion and data structure access and would probably use the union struct / array as described. It all depends on the application... Regards, Chris
From: John Devereux on 10 May 2010 11:25 ChrisQ <meru(a)devnull.com> writes: > John Devereux wrote: >> >> No, both techniques (your one and the "plain struct" approach) fail >> in an identical way when changing the number of elements or when a >> new compiler decides to re-arrange them. The elements will be in >> different locations. If you read an old structure with the new >> program (after a firmware update say) it will be corrupted. Wrapping >> the struct in a union does absolutely nothing to correct this! >> > > If you need to exchange data between systems, or if file format must be > constant, then it is a problem. The obvious solution is to > encapsulate all format conversion ops into a separate module and limit > access to the data structure(s) through function calls in that module. > That simplifies the management of risk for future maintenance. That's how > it would typically be done here and would also do it the long way round. > ie: Do the conversion from struct element(s) to an array element by element, > line by line. Then add plenty of commentary in the module and docs for > future maintainers. > > A good system design should always separate internal and external data > formats via conversion modules, but how often is that done in practice > ?. Typically, the internal struct is declared global, then peeked / > poked from everywhere and we wonder why the resulting system is a > nightmare to maintain and full of sleeping bugs. Well, fine, but this has nothing to do with the "plain struct" vs "wrapping in a union" argument. Nobody here is holding either up as Gold Standard of programming style. > Many embedded systems don't have the luxury of a clib style file system > (ie: only flash or cmos ram) and the internal "file system" is designed > / optimised to suit the app. Typically, the format needs no correlation > between versions, so changes to the structure have no effect at all. > Using a union to alias types involves some overhead, but it does make > the implied conversion clear. AFAIK the only "overhead" caused is in the mind of the poor programmer. The compiler ought to treat it the same as the plain struct. > I would use such techniques for any slightly dodgy conversion as it > makes the intent clear to the reader and compiler. After good design, > perhaps clarity should be the next most important thing. Good code > should flow down the page, with no pauses to do mental gymnastics re > the programmers intent :-). > >> So the "elements" are generic objects of length <size>, not >> specifically arrays. Of course everything is an "array of bytes" in >> the end but note that the first parameter is *not* "unsigned char*" >> (nor "U8*" either). >> > > One of the reasons to avoid the standard clib is that all the > types are wrong and casts are nearly always required. Far better > to develop your own libs over projects / years. I know half the world > runs embedded linux now, but can't shake off the perhaps neanderthal > view that unix is a better fit and unsurpassed on the desktop. Going > against the grain I know, but... I agree actually (about avoiding clib on microcontroller projects). It wasn't me that used fwrite() as an example, I had to look it up in the man page to find out what the parameters meant! -- John Devereux
From: Hans-Bernhard Bröker on 10 May 2010 17:16 ChrisQ wrote: > Perhaps not a good example. I would do: > > vFormatSave (&struct); > > With the structure defined in the associated module header file, hiding > all the format conversion away from the functions that use and save > it. And while doing so, if you're going to use that union hack you're so fond of, you'll end up having to copy your data into the union before you can use that union to --- copy the data to the actual output. How is copying twice better than copying once? > Many (most ?) self contained embedded systems don't need this > consistency, but would still encapsulate the conversion and data > structure access and would probably use the union struct / array as > described. No, they wouldn't, because their creators know that it serves no purpose at all.
From: Hans-Bernhard Bröker on 10 May 2010 17:34
ChrisQ wrote: > If you need to exchange data between systems, or if file format must be > constant, then it is a problem. Good. It took all of 7 weeks, but finally you understood what the problem stated by the OP was. > Using a union to alias types involves some overhead, but > it does make the implied conversion clear. No, it doesn't. It just causes undefined behaviour, and doesn't offer any noticeable advantage to balance that flaw. A person who needs a layer of syntactic overhead just to decipher an idiom as simple as a pointer to some data structure being passed to a generic data transport function should probably not be doing embedded C. It's gratuitous overhead like that that may very well make the difference between a project tightly fitting the limited resources of given hardware, and brutal failure. |