Thanks. I haven't tested it yet but i get the idea
Printable View
Thanks. I haven't tested it yet but i get the idea
Yes, because it's faster in the end, rather than having to convert the output to sensible data.
This one says it all:Quote:
And when you print the memory occupied by struct - char by char in hexa format, it is pretty easy to see what's stored in a struct (as long as we remember endianess issues and padding). I wonder where have you got the impression reading hexa is hard???
Plus you would to convert the output. Plus I am not too good at endianess & all that. It takes me some time to convert it.
And I'd have to use a calculator, and... well, no thanks.
In C, I would create functions to print the contents of different type of structs.
In C++, I would specialize cout for each struct type to print the contents.
No more so than hexa-decimal.Quote:
Another option is to use #ifdefs and and create debug structs which contain the size of struct as first member, and then type of members in struct. That way one could print whole struct's contents in more easily read format, and disable these prints after debug stage is over - with only one function, no matter how many different structs there is.
I guess it depends on software you're working with. The project in which I have been working last two years is a platform software for embedded realtime system. Since it relies heavily upon messaging, there's thousands of different message structs defined (and good deal of other structs). I believe making thousand of print functions would not be reasonable.
And just in case, I'll give an example of my second suggestion. Having:
This is just so the idea becomes clear...Code:
#ifdef DEBUGPRINT
typedef enum EStructMemberType
{
EStructMemberType_char = 0,
EStructMemberType_short,
EStructMemberType_int,
EStructMemberType_long,
.
.
.
EStructMemberType_Nmbrof
}EStructMemberType;
typedef struct Sfoo
{
int members;
EStructMemberType t_first;
int first;
EStructMemberType t_second;
long long int second;
EStructMemberType t_third;
void *third;
}Sfoo;
#else
typedef struct Sfoo
{
int first;
long long int second;
void *third;
}Sfoo;
#endif
#ifdef DEBUGPRINT
void Sprint(void *structPtr)
{
EStructMemberType type;
int members;
members=*(int *)structPtr;
type=*(EStructMemberType *) ( (int *)structPtr+1);
//handle printing each member...
}
#else
void Sprint(void *structPtr)
{
;
}
#endif
Naturally you can add other params to print function, like name of the struct, or filename and line number pointers. The Filename and linenumber could then be assigned by using some simple macro wrapper for print, Eg
Code:#define DBGPRINT_STRUCT(structptr) Sprint( (structptr), __FILE__, __LINE__)
void Sprint(void *structPtr, char *file, unsigned int line)
{
.
.
.
}
Seems more trouble than it's worth. But I'd probably just use a debugger to see the contents.
Debugger is great, but there's times when it:
Cannot be used, or is really troublesome to use - remember, we do embedded SW, which is not necessarily running on standard PC. Also at times we need info from things happening before debugger is usable...
Some failure occurs only after, lets say, ~10 hours of operartion. And problem may be such that it manages to mess the stack, causing backtrace being faulty... Imagine singlestepping the amount of code ran during 10 hours. Also many issues are such, that running the program in (SW) debugger may hide the problem. (For example synchronization related issues which often are highly timing critical).
Besides thread author did ask if there's a way to print struct's contents, not if it is reasonable. I guess it's up to him/her, and his/her needs to make decision about what way suits him/her needs.
Maz, itīs been interesting to read your approach on this- Originally I was interested to know if there where a function for this in the standard library or a method commonly used. But given that there arent any standard functions for this, all approaches to print to stdout are interesting to read about.
While we are on the subject of structs. You mentioned padding previously, and I have found that when I tried to write a struct to disk, using fwrite() the content of the struct were also padded. What are the options to solve that?
I for example had a struct with some ints, strings, and short data types. Now, when I use fwrite() to write the struct 'form' like this:
All shorts occupy 4 bytes on the created file.Code:fwrite(&form, sizeof(form), 1, fpAIF);
Indeed, I do get what you say. It has happened to some of my software, as well.
So, a combination of those two methods is the best I can think of.
You would have to either a) remove padding (not recommended) or b) write out each member of the struct individually and read them back individually or c) accept the padding.
Elysia, I have went with option b. for now just to get it to work. What are the issues with turning of the padding, if itīs for one particular function only? Accepting the padding wont work in this case, Iīm using the struct to write a fileheader so each field has to comply to the spec of the format.
The best way to write a file header is to print each field individually, to avoid padding issues.
Padding is added to increase performance, since reading or writing on a "unaligned address" causes performance penalty for the CPU.
You normally do not have to worry about padding, though. Only know that sometimes extra "invisible" variables might be added to a struct.
OK got it, Iīm going to stick with what I have then. Thanks.
You can eliminate padding by using pragmas for example - unfortunately there is no standardized pragma, so portability is probs broken.
However, one handy way is to add unused "padding" fields in struct. Eg: following would probs be working in most of the systems:
Code:struct padded
{
char foo; //used1 1 byte
char bar; //used2 2 byte => align not ok, since next is int.
short padding1; //unused, just to eliminate padding //3 && 4 byte => properly aligned
int foobar; // 4bytes => align ok.
char * barfoo; // 4 bytes (or 8 bytes, depends on arch), => alignment ok.
short fb; //short => 2 bytes => alignment broken.
short padding2;
};
"manual" alignment, however, relies on the programmer understanding and agreeing with the compiler about what alignment goes where and what the rules for "proper alignment is".
If you have freedom to arrange your struct the way you like, placing the members in size order (largest to smallest) from the beginning to the end of the struct will work well, as it avoids the problem of larger members needing to have padding to fill out space(s) left by a smaller member. Note that by "Largest", I mean the align-regulating member, so a "long long" that is 8 bytes is bigger in "alignment size" (8) than an array of 4000 characters because this is just one char in "aligning size" (1).
And whilst Elysia is correct that alignment is added for speed improvement, there are processors that do not work correctly if you use unaligned data (e.g. 68000, Sparc, Alpha, PDP-11, VAX and many others). x86 doesn't care about alignment from a functional perspective, it just takes a bit longer to load/store the data from/to an unaligned address.
--
Mats