reading a structure containing pointers
Author |
Message |
Tom Impellus #1 / 9
|
 reading a structure containing pointers
Hello I have never done or thought about this... Say I ahve this structure: struct moon { int moon_id; char name[100]; float distance; float rotate; Quote: };
Clearly, I can do a read: struct moon *m; m = (struct moon*) malloc(10 * sizeof(struct moon)); i = write(fd, m, 10 * sizeof(stuct moon)); But suppose I had this: struct moon { int moon_id; char *name float distance; float rotate; Quote: }
and somewhere, I ensured that m->name was pointing at a space of , say, 100 bytes. Is there a way to do the same type of write, or read?
|
Sun, 20 Apr 2003 04:26:51 GMT |
|
 |
Mark A. Ode #2 / 9
|
 reading a structure containing pointers
Quote: >and somewhere, I ensured that m->name was pointing at a space >of , say, 100 bytes. >Is there a way to do the same type of write, or read?
Yes, I think we covered this last week here. Re-write so the variable thingys are at the end of the struct like this: typedef struct { int moon_id; float distance; float rotate; char name[1]; /* Yes, one */ Quote: } Moon;
int thisNameLen = strlen("Io"); /* Do *NOT* cast the return value of malloc(), read the C-FAQ for why. ** Note that strlen only counts two here but since name[1] is already ** one long in the Moon object we don't need to add one for the nul char. */ Moon *pMoon = malloc(sizeof *pMoon + thisNameLen); if (*pMoon) { /* You might consider fwrite, write is not ISO C */ i = write(fd, pMoon, sizeof *pMoon); free(pMoon); Quote: }
Note exactly what you want since you need to do this for each Moon you want but you get the idea. I'm sure you can extend this out.
|
Sun, 20 Apr 2003 04:39:21 GMT |
|
 |
naisbod #3 / 9
|
 reading a structure containing pointers
Quote:
> Say I ahve this structure: > struct moon { > int moon_id; > char name[100]; > float distance; > float rotate; > }; > Clearly, I can do a read: > struct moon *m; > m = (struct moon*) malloc(10 * sizeof(struct moon)); > i = write(fd, m, 10 * sizeof(stuct moon));
Try not to refer to the type of the variable, for several reasons. You could do: m = malloc (10 * sizeof *m); i = write (fd, m, 10 * sizeof *m)); OTOH, write is a POSIX function. For questions related to POSIX functions, please post on comp.unix.programmer. This newsgroup is about the ISO/ANSI standards for C. Note that the ISO functions to do the same task here are fwrite and fread, and not all implementations will have write/read. Quote: > But suppose I had this: > struct moon { > int moon_id; > char *name > float distance; > float rotate; > } > and somewhere, I ensured that m->name was pointing at a space > of , say, 100 bytes. > Is there a way to do the same type of write, or read?
Yes, but it's not meaningful. You'll want to write out the struct first, then the data at *name. Note that the pointer you've written to disk will be meaningless in the loading function. When reading it, read the struct first, allocate space at name, and then read the pointer into the space you allocated. The key here is to discard the value you've written for name. --
|
Sun, 20 Apr 2003 04:47:17 GMT |
|
 |
Robert Stankowi #4 / 9
|
 reading a structure containing pointers
Quote:
> Hello > I have never done or thought about this... > Say I ahve this structure: > struct moon { > int moon_id; > char name[100]; > float distance; > float rotate; > }; > Clearly, I can do a read: > struct moon *m; > m = (struct moon*) malloc(10 * sizeof(struct moon)); > i = write(fd, m, 10 * sizeof(stuct moon)); > But suppose I had this: > struct moon { > int moon_id; > char *name > float distance; > float rotate; > } > and somewhere, I ensured that m->name was pointing at a space > of , say, 100 bytes. > Is there a way to do the same type of write, or read?
Not with a simple fwrite(), and the file will not be portable. If you just want to write and read it on the same system you could do something like: fwrite(fd, m, sizeof(struct moon)); int i=strlen(name); fwrite(fd, i, sizeof(int)); fwrite(fd, name, i); and on read: read the struct read the strlen allocate space for the string read the string Altogether a really hard way, and not portable at all. Easier, more (but not fully) portable and with the advantage that your file will be readable by human eyes will be to write the members of the struct to a text file using fprintf and read them back using fscanf. Regards Robert
|
Sun, 20 Apr 2003 03:45:21 GMT |
|
 |
C #5 / 9
|
 reading a structure containing pointers
Quote:
> Hello > I have never done or thought about this... > Say I ahve this structure: > struct moon { > int moon_id; > char name[100]; > float distance; > float rotate; > }; > Clearly, I can do a read: > struct moon *m; > m = (struct moon*) malloc(10 * sizeof(struct moon)); > i = write(fd, m, 10 * sizeof(stuct moon)); > But suppose I had this: > struct moon { > int moon_id; > char *name > float distance; > float rotate; > } > and somewhere, I ensured that m->name was pointing at a space > of , say, 100 bytes. > Is there a way to do the same type of write, or read?
byte reading/writing structs like that isnt very portable in any case. in the second case, it would write the contents of the pointer variable, which usually would be some sort of address and would not be valid after the prog that writes it exits. you should make an algorithm to store each struct/field in ASCII form, then make another to re-read it back up into the struct. - BIG FAT LOAFER
|
Sun, 20 Apr 2003 06:00:05 GMT |
|
 |
Andoma #6 / 9
|
 reading a structure containing pointers
Quote: > /* Do *NOT* cast the return value of malloc(), read the C-FAQ for why. > ** Note that strlen only counts two here but since name[1] is already > ** one long in the Moon object we don't need to add one for the nul char. > */
If I remember ok (couldn't find the entry in the C-FAQ you were referring too) the pro and con of casting were: Pro casting: will compile with a K&R or C++ compiler Con casting: you don't get a compiler warning/error if you forget to include stdlib.h Forget to include stblib.h and compiler will assume malloc() returns an integer. This could fail on systems were int is different from void*. Is this right or am I missing something obvious? By the way there are many docs on the Internet which advocate casting: ------------ From the GNU docs for malloc(): The contents of the block are undefined; you must initialize it yourself (or use calloc instead; see section Allocating Cleared Space). Normally you would cast the value as a pointer to the kind of object that you want to store in the block. Here we show an example of doing so, and of initializing the space with zeros using the library function memset (see section Copying and Concatenation): struct foo *ptr; ... ptr = (struct foo *) malloc (sizeof (struct foo)); if (ptr == 0) abort (); memset (ptr, 0, sizeof (struct foo)); You can store the result of malloc into any pointer variable without a cast, because ISO C automatically converts the type void * to another type of pointer when necessary. But the cast is necessary in contexts other than assignment operators or if you might want your code to run in traditional C. ------- From the SYSTEM V unix man page: Note: Always cast the value returned by malloc(), realloc(), calloc(), memalign(), valloc() or alloca(). ------- Verify for yourself at: http://www.gnu.org/manual/glibc-2.0.6/html_chapter/libc_3.html http://www.cs.princeton.edu/courses/archive/spring00/cs217/assignment... loc.3.html
|
Sun, 20 Apr 2003 15:49:40 GMT |
|
 |
naisbod #7 / 9
|
 reading a structure containing pointers
Quote:
> If I remember ok (couldn't find the entry in the C-FAQ you were > referring too)
http://www.eskimo.com/~scs/C-faq/q7.7.html Quote: > the pro and con of casting were: > Pro casting: will compile with a K&R or C++ compiler
Why would I want my code to compile in a compiler written for another language? I could even further restrict the usefulness of my code by figuring out ways it could pass as Perl or Java, I suppose. Does that sound like a good idea to you too? For that matter, K&R C can be considered a separate language from C90, just as C90 can be considered separate from C99. The difference is, C99 is coming, but K&R C is gone. Therefore it's implied that one should try to keep code valid for C99, but not at all so for K&R C. Quote: > Con casting: you don't get a compiler warning/error if you > forget to include stdlib.h
What if the sizeof void * != sizeof int? What if the two are stored differently for some reason? The warning might not just be superficial. Once, long ago, I forgot to include <math.h> and my compiler didn't warn me about a lack of prototypes. Just calling pow crashed. I assume somewhere, something similar could happen with malloc. Quote: > From the GNU docs for malloc(): > ptr = (struct foo *) malloc (sizeof (struct foo)); > if (ptr == 0) abort (); > memset (ptr, 0, sizeof (struct foo));
This is all nice, except I'd do at least five things differently for readability and portability reasons. Maybe something like this: ptr = malloc (sizeof *ptr); if (ptr == NULL) exit(EXIT_FAILURE); memset (ptr, 0, sizeof *ptr); Besides, since when is GNU authoritative? *ducks* Quote: > Note: Always cast the value returned by malloc(), realloc(), calloc(), > memalign(), valloc() or alloca().
It also says to include <malloc.h>. What do you think you should infer from this fact? Anyway, please do a search on dejanews for this subject, so you can see what arguments have already been had on it. I'm sure many people have done a better job of refuting your point already. --
|
Sun, 20 Apr 2003 07:47:26 GMT |
|
 |
Mark A. Ode #8 / 9
|
 reading a structure containing pointers
Quote: >If I remember ok (couldn't find the entry in the C-FAQ you were >referring too) the pro and con of casting were: >Pro casting: will compile with a K&R or C++ compiler >Con casting: you don't get a compiler warning/error if you > forget to include stdlib.h >Forget to include stblib.h and compiler will assume malloc() >returns an integer. This could fail on systems were int is different >from void*.
This is correct. Quote: >Is this right or am I missing something obvious? >By the way there are many docs on the Internet which >advocate casting: >------------ >From the GNU docs for malloc():
Give me a reason for casting a void *? C will auto-cast (my words) the returned pointer to match the pointer it's being assigned to. You can put parenthesis around everything to, doesn't mean you should. Quote: >You can store the result of malloc into any pointer variable without a cast, >because ISO C automatically converts the type void * to another type of >pointer when necessary. But the cast is necessary in contexts other than >assignment operators or if you might want your code to run in traditional C.
Traditional C? I only worry about ANSI/ISO C and the extensions my modern compiler apply to the platform I'm working on. I have a luxury it would seem. Quote: >------- >From the SYSTEM V unix man page: >Note: Always cast the value returned by malloc(), realloc(), calloc(), >memalign(), valloc() or alloca().
At one point I think they recommended cutting holes in your scull if you had headaches. They dropped that practice just after the cast on malloc's return value.
|
Sun, 20 Apr 2003 09:11:55 GMT |
|
 |
Richard B #9 / 9
|
 reading a structure containing pointers
Quote:
> > /* Do *NOT* cast the return value of malloc(), read the C-FAQ for why. > > ** Note that strlen only counts two here but since name[1] is already > > ** one long in the Moon object we don't need to add one for the nul char. > > */ > If I remember ok (couldn't find the entry in the C-FAQ you were > referring too) the pro and con of casting were: > Pro casting: will compile with a K&R or C++ compiler
No, it won't, unless there are no more interesting lines in the code than your malloc() call. There are many more things in ISO C that won't compile in C++; a variable called new is just one trivial example. Ditto for K&R; for example, would you remove all prototypes from your code just to keep it compiling under K&R? You'll have to, you know. Quote: > Con casting: you don't get a compiler warning/error if you > forget to include stdlib.h
And: is likely to break if you ever change the type of the pointer. And, perhaps most importantly: it gives the wrong semantic message. Sure, it may work, but you give the impression that you think the cast is necessary, or that something weird is going on. Never cast things you don't have to cast; a cast should be a red flashing light telling you that something is out of the ordinary here, not something you use because it happens to make your broken code compile. A wrong cast can be a time-bomb in your code. Don't, ever, cast unless you know that you _must_, and you also know _why_. Quote: > Forget to include stblib.h and compiler will assume malloc() > returns an integer. This could fail on systems were int is different > from void*.
It could fail under a lot of circumstances, including ints being as large as void *s, but being returned in different registers. Quote: > Is this right or am I missing something obvious? > By the way there are many docs on the Internet which > advocate casting: > ------------ > From the GNU docs for malloc():
Don't, ever, take anything GNU claims as authoritative or even likely to be true under ISO C. Their attitude towards compliance is as arrogant as it is deplorable. Quote: > From the SYSTEM V unix man page:
That's not only ancient, it's system-specific and meant to be. Richard
|
Sun, 20 Apr 2003 18:37:30 GMT |
|
|
|