[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

is this legal (and ANSI89 conforming) C?

dr.oktopus

6/22/2011 5:27:00 PM

Hello,
suppose that I have to create a dummy node of a list data type
that references itself (like in Sedgewick book). Is this:

struct node {
struct node *next;
int c;
} dummy_node = { &dummy_node };

legal? I think no problem should be, but I want a confirm.
18 Answers

Tom St Denis

6/22/2011 6:36:00 PM

0

On Jun 22, 1:26 pm, "dr.oktopus" <blindwi...@freeonline.zzn.com>
wrote:
> Hello,
> suppose that I have to create a dummy node of a list data type
> that references itself (like in Sedgewick book). Is this:
>
> struct node {
>     struct node *next;
>     int c;
>
> } dummy_node = { &dummy_node };
>
> legal? I think no problem should be, but I want a confirm.

IIRC it's valid because once you declare the variable you can use it
right away.

Anyone who writes code like that should be shot though. Or at least
mildly beaten with a foam clue bat.

Tom

cr88192

6/22/2011 7:50:00 PM

0

On 6/22/2011 11:35 AM, Tom St Denis wrote:
> On Jun 22, 1:26 pm, "dr.oktopus"<blindwi...@freeonline.zzn.com>
> wrote:
>> Hello,
>> suppose that I have to create a dummy node of a list data type
>> that references itself (like in Sedgewick book). Is this:
>>
>> struct node {
>> struct node *next;
>> int c;
>>
>> } dummy_node = {&dummy_node };
>>
>> legal? I think no problem should be, but I want a confirm.
>
> IIRC it's valid because once you declare the variable you can use it
> right away.
>
> Anyone who writes code like that should be shot though. Or at least
> mildly beaten with a foam clue bat.
>

IIRC Quake contained some code which looked like that in a few places...


well, along with a lot of:
read a file into a glob of memory;
do some pointer arithmetic (adding file offsets, ...);
cast the pointers to structs.

IMO though, this isn't a very good way to load binary files. my personal
preference is more to have code which reads in/decodes the contents of
the files (reading out individual values, ...), and puts them into newly
allocated memory.


or such...

Angel

6/22/2011 8:00:00 PM

0

On 2011-06-22, BGB <cr88192@hotmail.com> wrote:
>
> IIRC Quake contained some code which looked like that in a few places...
>
>
> well, along with a lot of:
> read a file into a glob of memory;
> do some pointer arithmetic (adding file offsets, ...);
> cast the pointers to structs.

That's similar to the code I posted here a couple of weeks ago. It's not
portable due to padding (I used a gcc extension to turn padding off
entirely), endianness and unaligned access.

> IMO though, this isn't a very good way to load binary files. my personal
> preference is more to have code which reads in/decodes the contents of
> the files (reading out individual values, ...), and puts them into newly
> allocated memory.

That's how I rewrote it, and I agree, it makes for much cleaner code. It
is more work though. :-)


--
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c

Tom St Denis

6/22/2011 8:40:00 PM

0

On Jun 22, 3:49 pm, BGB <cr88...@hotmail.com> wrote:
> On 6/22/2011 11:35 AM, Tom St Denis wrote:
>
>
>
> > On Jun 22, 1:26 pm, "dr.oktopus"<blindwi...@freeonline.zzn.com>
> > wrote:
> >> Hello,
> >> suppose that I have to create a dummy node of a list data type
> >> that references itself (like in Sedgewick book). Is this:
>
> >> struct node {
> >>      struct node *next;
> >>      int c;
>
> >> } dummy_node = {&dummy_node };
>
> >> legal? I think no problem should be, but I want a confirm.
>
> > IIRC it's valid because once you declare the variable you can use it
> > right away.
>
> > Anyone who writes code like that should be shot though.  Or at least
> > mildly beaten with a foam clue bat.
>
> IIRC Quake contained some code which looked like that in a few places...
>
> well, along with a lot of:
> read a file into a glob of memory;
> do some pointer arithmetic (adding file offsets, ...);
> cast the pointers to structs.
>
> IMO though, this isn't a very good way to load binary files. my personal
> preference is more to have code which reads in/decodes the contents of
> the files (reading out individual values, ...), and puts them into newly
> allocated memory.
>
> or such...

ID Software was not known for writing what could be called "portable"
software. At the very least in CLC the idea is code snippets should
be portable.

I think the above code is correct [portable] just not very useful and
as a design decision I'd avoid that sort of declaration/initialization
code. I'm also not a big fan of code like

int a=4,b,c,d=5;
// etc...

I think legibility is increased if declarations are in one block, and
initializers in another...

int a,b,c,d;

a = 4;
d = 5;

// code...

As a general rule aside from going crazy on the prettyness every
minute spent writing proper code is 5 minutes saved on debugging.
Being able to quickly scan code for "is this variable initialized and
if so to what?" is very handy.

cr88192

6/22/2011 10:23:00 PM

0

On 6/22/2011 1:39 PM, Tom St Denis wrote:
> On Jun 22, 3:49 pm, BGB<cr88...@hotmail.com> wrote:
>> On 6/22/2011 11:35 AM, Tom St Denis wrote:
>>
>>
>>
>>> On Jun 22, 1:26 pm, "dr.oktopus"<blindwi...@freeonline.zzn.com>
>>> wrote:
>>>> Hello,
>>>> suppose that I have to create a dummy node of a list data type
>>>> that references itself (like in Sedgewick book). Is this:
>>
>>>> struct node {
>>>> struct node *next;
>>>> int c;
>>
>>>> } dummy_node = {&dummy_node };
>>
>>>> legal? I think no problem should be, but I want a confirm.
>>
>>> IIRC it's valid because once you declare the variable you can use it
>>> right away.
>>
>>> Anyone who writes code like that should be shot though. Or at least
>>> mildly beaten with a foam clue bat.
>>
>> IIRC Quake contained some code which looked like that in a few places...
>>
>> well, along with a lot of:
>> read a file into a glob of memory;
>> do some pointer arithmetic (adding file offsets, ...);
>> cast the pointers to structs.
>>
>> IMO though, this isn't a very good way to load binary files. my personal
>> preference is more to have code which reads in/decodes the contents of
>> the files (reading out individual values, ...), and puts them into newly
>> allocated memory.
>>
>> or such...
>
> ID Software was not known for writing what could be called "portable"
> software. At the very least in CLC the idea is code snippets should
> be portable.
>

fair enough...

with some modest modifications, I had it working on Windows x64 before.
I later briefly tried building this version on Linux x86-64, but it
tended to crash when doing "new game" (and then managed to effectively
break X11 requiring a hard-reboot), and at the time I didn't really
bother enough with trying to use GDB to make it fully work (one can get
spoiled with things like the Visual Studio debugger and similar...).


and, people have also got it working on a number of exotic
architectures, so its portability probably isn't that terrible.


I have my own 3D engine (vaguely Quake-like, but written clean so as to
hopefully be free of the GPL, and internally working somewhat
differently), which does build and work on Linux x86-64 at present, but
does have a few theoretical technical issues (the theory goes that
calling variable-argument C functions from my custom script-language
"should" be prone to misbehave/blow-up due to how varargs and the AMD64
ABI are handled at present, and I would have to partly rework the
existing function-call mechanism to fix this...). currently, it calls
the functions with garbage in the variable arguments.

I may later integrate "printf" directly into my script-VM (as a builtin
function), since I call it a lot from scripts, and this is the main
function likely to encounter this issue, but Linux is not a highly
important target at the moment, so I may address this when I get to it.

also, lots of work and debugging is needed in general.


whether or not though I can create a complete game though is another
issue, as there is a lot of work needed in areas I am not very good
enough (mostly "content creation" type issues), before one has something
which anywhere compares with anything people would probably willingly
pay money for (and not feel ripped off...).



> I think the above code is correct [portable] just not very useful and
> as a design decision I'd avoid that sort of declaration/initialization
> code.

yes, ok.


> I'm also not a big fan of code like
>
> int a=4,b,c,d=5;
> // etc...
>
> I think legibility is increased if declarations are in one block, and
> initializers in another...
>
> int a,b,c,d;
>
> a = 4;
> d = 5;
>
> // code...
>

agreed, I tend to do similar...


> As a general rule aside from going crazy on the prettyness every
> minute spent writing proper code is 5 minutes saved on debugging.
> Being able to quickly scan code for "is this variable initialized and
> if so to what?" is very handy.

I try to make tradeoffs...

prettyness, good style, ... matter some, but ultimately, getting things
written and working is a better strategy.

for example, "perfect" code is of little value if it is never written or
put to use. often, code can be just plain nasty, and the product still
gets written and working (the horrible nastiness just left for whoever
dares look at the source).

but, ideally, a person can still try to make the code look nice where
possible.

Shao Miller

6/23/2011 12:25:00 AM

0

On 6/22/2011 12:26 PM, dr.oktopus wrote:
> Hello,
> suppose that I have to create a dummy node of a list data type
> that references itself (like in Sedgewick book). Is this:
>
> struct node {
> struct node *next;
> int c;
> } dummy_node = {&dummy_node };
>
> legal? I think no problem should be, but I want a confirm.

I don't think it's good. 'dummy_node' does not have 'static' storage
duration. Sorry! :)

Shao Miller

6/23/2011 12:34:00 AM

0

On 6/22/2011 7:24 PM, Shao Miller wrote:
> On 6/22/2011 12:26 PM, dr.oktopus wrote:
>> Hello,
>> suppose that I have to create a dummy node of a list data type
>> that references itself (like in Sedgewick book). Is this:
>>
>> struct node {
>> struct node *next;
>> int c;
>> } dummy_node = {&dummy_node };
>>
>> legal? I think no problem should be, but I want a confirm.
>
> I don't think it's good. 'dummy_node' does not have 'static' storage
> duration. Sorry! :)

As a work-around, perhaps you'd enjoy:

struct node {
struct node * next;
int c;
};

struct node * init_node(struct node * node) {
/* Initialize the node */
node->next = node;
return node;
}

int main(void) {
struct node dummy_node, * dp = init_node(&dummy_node);
/*
* Simply don't use 'dp' and hopefully it's
* optimized away...
*/
return 0;
}

Eric Sosman

6/23/2011 1:57:00 AM

0

On 6/22/2011 2:35 PM, Tom St Denis wrote:
> On Jun 22, 1:26 pm, "dr.oktopus"<blindwi...@freeonline.zzn.com>
> wrote:
>> Hello,
>> suppose that I have to create a dummy node of a list data type
>> that references itself (like in Sedgewick book). Is this:
>>
>> struct node {
>> struct node *next;
>> int c;
>>
>> } dummy_node = {&dummy_node };
>>
>> legal? I think no problem should be, but I want a confirm.
>
> IIRC it's valid because once you declare the variable you can use it
> right away.

Yes. The scope of the identifier `node' begins immediately
after its first appearance, so it's in scope when mentioned on
the next line. The scope of the identifier `dummy_node' begins
immediately after its declarator (that is, just before the `='),
so it's in scope when used in the initializer.

> Anyone who writes code like that should be shot though. Or at least
> mildly beaten with a foam clue bat.

It seems to me a perfectly ordinary and laudable way to intialize
a circular linked list, possibly considered "empty" if `dummy_node'
is regarded as a "list header." (Some compilers will probably warn
about non-initialization of the `c' element, but I think that's not
the thrust of the question.) What alternative construct would you
suggest?

--
Eric Sosman
esosman@ieee-dot-org.invalid

Shao Miller

6/23/2011 6:08:00 AM

0

On 6/22/2011 8:57 PM, Eric Sosman wrote:
> On 6/22/2011 2:35 PM, Tom St Denis wrote:
>> On Jun 22, 1:26 pm, "dr.oktopus"<blindwi...@freeonline.zzn.com>
>> wrote:
>>> Hello,
>>> suppose that I have to create a dummy node of a list data type
>>> that references itself (like in Sedgewick book). Is this:
>>>
>>> struct node {
>>> struct node *next;
>>> int c;
>>>
>>> } dummy_node = {&dummy_node };
>>>
>>> legal? I think no problem should be, but I want a confirm.
>>
>> IIRC it's valid because once you declare the variable you can use it
>> right away.
>
> Yes. The scope of the identifier `node' begins immediately
> after its first appearance, so it's in scope when mentioned on
> the next line. The scope of the identifier `dummy_node' begins
> immediately after its declarator (that is, just before the `='),
> so it's in scope when used in the initializer.
>

I could be mistaken, but for C89:

- I believe that an initializer for a 'struct', 'union', or array must
be a constant expression.

- I believe that '&dummy_node' is not an address constant because
'dummy_node' is not an object with 'static' storage duration.

"Work-around" code given elsethread.

Tim Rentsch

6/23/2011 8:16:00 AM

0

"dr.oktopus" <blindwilly@freeonline.zzn.com> writes:

> Hello,
> suppose that I have to create a dummy node of a list data type
> that references itself (like in Sedgewick book). Is this:
>
> struct node {
> struct node *next;
> int c;
> } dummy_node = { &dummy_node };
>
> legal? I think no problem should be, but I want a confirm.

Yes if the definition is given in file scope, or
in block scope in C99; no for block scope in C89.