As a C programmer who hangs out in comp.lang.c, I’m strongly tempted to get out a copy of C99 so that I can tell you precisely where you’re wrong there. But I’ll content myself with pointing out that there is no guarantee that sizeof(long)==2*sizeof(short)==4*sizeof(char), and moreover that even if that did hold, there is still no guarantee that sizeof(struct {short hi; short lo;})==2*sizeof(short) because the struct might have padding—what if ‘short’ were a 16 bit quantity but stored in 32 bit words (perhaps because the arch can only do 32 bit writes, and has decided that short should be an int_fast16_t rather than an int_least16_t), resulting in alignment requirements?
In conclusion, PK should learn some basic C, and forget about the ++. (Old joke: what does C++ mean? Take C, add to it, then use the old version)
EDIT: thanks, paper-machine, and I approve of Markdown’s choice of escape character. Now, if it’ll just let me use \033[1;35m to change the colour...
I don’t see anything wrong with grandparent, assuming a particular architecture. And whenever I used to write c, it was almost always for a particular architecture, usually with inlined assembly. Am I missing something, or are you just trying to make some point about portability regarding a metaphor?
It is a lesson hard-learned over many programmer-years of coding that portability should be acquired as an innate reflex; that whenever you are about to sacrifice portability, you ask yourself “Why am I doing so, are there alternatives, and have I done at least a rudimentary cost/benefit analysis of this decision?”
What you don’t do is throw away portability just because you happen to be using a particular machine right now. This is something quickly learned in comp.lang.c.
Incidentally, a better model than PK’s might be:
typedef struct foo {int i} s;
s f;
Now what is ‘f’? Is it an ‘s’, is it a struct foo, or is it an int? And what about f.i? Both have the same address, casting either’s address to any of the pointer types ‘s *’, ‘struct foo *’ or ‘int *’ is valid; writing
*(int *)&f=1;
does just the same as f.i=1; quite possibly the compiler will generate the same code, because after all, the territory is the same. It’s just that “f.i=1” is a higher-level map, which conveniently abstracts things out.
This is made more explicit by considering struct bar {int a; long b;} t; *(long *)(((char *)&bar)+offsetof(bar, b))=1; // same as bar.b=1
Of course, you could go to all the trouble of computing the offset pointer every time, since that’s what happens on the “quark” (assembly language) level of the territory, but the higher-level ‘struct’ map is cognitively useful.
As a C programmer who hangs out in comp.lang.c, I’m strongly tempted to get out a copy of C99 so that I can tell you precisely where you’re wrong there. But I’ll content myself with pointing out that there is no guarantee that sizeof(long)==2*sizeof(short)==4*sizeof(char), and moreover that even if that did hold, there is still no guarantee that sizeof(struct {short hi; short lo;})==2*sizeof(short) because the struct might have padding—what if ‘short’ were a 16 bit quantity but stored in 32 bit words (perhaps because the arch can only do 32 bit writes, and has decided that short should be an int_fast16_t rather than an int_least16_t), resulting in alignment requirements?
In conclusion, PK should learn some basic C, and forget about the ++. (Old joke: what does C++ mean? Take C, add to it, then use the old version)
EDIT: thanks, paper-machine, and I approve of Markdown’s choice of escape character. Now, if it’ll just let me use \033[1;35m to change the colour...
I don’t see anything wrong with grandparent, assuming a particular architecture. And whenever I used to write c, it was almost always for a particular architecture, usually with inlined assembly. Am I missing something, or are you just trying to make some point about portability regarding a metaphor?
It is a lesson hard-learned over many programmer-years of coding that portability should be acquired as an innate reflex; that whenever you are about to sacrifice portability, you ask yourself “Why am I doing so, are there alternatives, and have I done at least a rudimentary cost/benefit analysis of this decision?”
What you don’t do is throw away portability just because you happen to be using a particular machine right now. This is something quickly learned in comp.lang.c.
Incidentally, a better model than PK’s might be:
typedef struct foo {int i} s;
s f;
Now what is ‘f’? Is it an ‘s’, is it a struct foo, or is it an int? And what about f.i? Both have the same address, casting either’s address to any of the pointer types ‘s *’, ‘struct foo *’ or ‘int *’ is valid; writing
*(int *)&f=1;
does just the same as f.i=1; quite possibly the compiler will generate the same code, because after all, the territory is the same. It’s just that “f.i=1” is a higher-level map, which conveniently abstracts things out.
This is made more explicit by considering struct bar {int a; long b;} t; *(long *)(((char *)&bar)+offsetof(bar, b))=1; // same as bar.b=1
Of course, you could go to all the trouble of computing the offset pointer every time, since that’s what happens on the “quark” (assembly language) level of the territory, but the higher-level ‘struct’ map is cognitively useful.
Upvoted for delicious, delicious C.
EDIT: However, you may want to work on the markdown; * is a reserved character ;_;