Is it possible to display a struct in stdout in one go? Letīs say you got a struct with different data types, it would be convenient to be able to print to stdout reffering only to the struct, not the individual members.
Printable View
Is it possible to display a struct in stdout in one go? Letīs say you got a struct with different data types, it would be convenient to be able to print to stdout reffering only to the struct, not the individual members.
Short answer is no.
If you're using gcc with the GNU LibC, then you can hook in your own printf format styles, but you might be pushing your luck with structs.
Thanks Salem. I am using gcc but I think Iīm going to take no for an answer, for now at least.
You can at least print struct as chars. Do a print function which takes structs size ptr to struct as void ptr.
Then just print the values in structs as chars in hexa format (in loop). When you know what struct you printed, you can quite easily calculate the values of independent members later. Just remember that if you do not have used any packing pragmas, compilers often add padding to keep default (usually 32 bit) alignation (or how do you say that).
Maz, thatīs an interesting approach. Iīll look into it.
Cheers.
That is not a very good solution... it gives pretty much some "non-sensical" output since all the data would be printed as hexa-decimal and it's not immediately obvious (perhaps ever?) what they are.
I suppose not, but you could write a custom function to output the data. Then all it would take is a single line to call the function.
No doubt I'm stating the obvious, but you can always wrap your struct-displaying code into one function.
In C++, you can overload the << operator for your data type, but of course this isn't possible in C.Code:struct person {
char *age;
int name;
};
void print_person(struct person who) {
printf("%s, age %d", who->name, who->age);
}
struct person joe;
joe.name = malloc(10);
strcpy(joe.name, "Joe");
joe.age = 33;
print_person(joe);
printf("\n");
I have been trying that, but never successfully :-D. I was not sure how I should interpret that it was not possible, started to fear that making a print function was out of the question.
This is what I have come up with so far.
main:
printStruct:Code:typedef struct {
int foo;
char name[25];
} Test;
Test myTest;
int *pt = NULL;
myTest.foo = 100;
myTest.name[0] = 'F';
myTest.name[1] = 'r';
myTest.name[2] = 'e';
myTest.name[3] = 'd';
printStruct(&myTest.foo);
This outputs the int correctly but only the last letter of name.Code:int printStruct(int *first) {
int foo;
char name[25];
foo = *first;
printf("Foo: %d\n", foo);
first++;
name[0] = (char)*first;
printf("Name: %s\n", name);
return 0;
}
dwks,
Some of that code looks a bit forreign to me still, what is the -> operator doing?
Thanks guys!
pTest->foo is the same as (*pTest).foo.Code:typedef struct
{
int foo;
char name[25];
} Test;
int main()
{
Test myTest;
myTest.foo = 100;
strcpy(myTest.name, "Fred");
printStruct(&myTest);
}
void printStruct(Test* pTest)
{
printf("Foo: %d\n", pTest->foo);
printf("Name: %s\n", pTest->name);
}
You were making this much harder than it needs be. I'm guessing you haven't learned all that much about C, yet.
So you suggest writing own print function for each struct?
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???
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 never could restore the float value looking at its hex representation...Quote:
I wonder where have you got the impression reading hexa is hard???
Interesting. Can you give an example to illustrate your point?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).
Allright peeps. I did not mean to start a war (here too) ;)
And I admitt I forgot the floats and doubles, they're harder. It has been long since I last needed floats or doubles. But I am positive that with a decent amount of searching, you can find out how they're represented, and when you convert hexas to binary, take your calculator and spend some time more, you'll eventually have those solved too :D
simple non tested, straight to post coded example:
example:Code:void print_struct( void *struct, size_t structSize)
{
size_t i;
char *printme=(char *)struct;
int formatter=1;
for( i=0;i < structSize;i++ )
{
printf("%02x ",*printme++):
if(!(formatter%4))
{
printf("\n");
}
}
}
typedef struct foo
{
int first;
char second;
char third;
char fourth;
void *fifth;
}foo;
print might produce:
A1 00 00 00
4D 61 7A 00
00 00 00 00
Now we can analyze this,
Knowing I am using PC in 32 bit arch, I know addresses are 32 bit wide, and it uses little endian arch. So let's see.
first 4 bytes (first row) is the int's value. Little endian system, so least significant bytes are first, EG int is A1 in hexa, which is 161 in ints. Then tehre's 3 chars, Eg chars 4D 61 7A. Quick look at ASCII table says, it is Maz.
The last 00 in that row is pretty likely to be the padding, to maintain default 32 bit alignation.
Last is void pointer, and as we see it is pointing at NULL address.
What was the hard part?
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