We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
struct NODE{ struct NODE Succ; struct NODE Prev; }; struct LIST{ struct NODE *Head; struct NODE *Tail; int count; }; struct LIST *List; struct NODE *N; ...... for(N = List->Head;N;N = N->Succ) { ...... }
Hi, That's strange; on AmigaOS it is basic feature of doubly linked lists. Maybe for workaround, you should create temporal pointer, something like:
struct NODE *N, *tn; ...... for(N = List->Head;N;tn = N->Succ, N=tn)
Your report is crucially incomplete. How do you detect that something happened to List->Head? There's not even a vague hint of actual results of running this code in your posting. And what side effect of
N=N->Succ
struct NODE{ struct NODE Succ; // should be *Succ struct NODE Prev; // should be *Prev };
You are right,I forgot asterisk.the orignal source code is as follow:
struct NODE{ struct NODE *Succ; struct NODE *Prev; };
N = N->Succ;
List->Head = List->Head->Succ;
N = List->Head;
I have tried your code with some init statements and could not find out, that the list items ((Head/Tail) get changed after loop execution - the compiler works properly. Maybe you have some other additional code that changes the structure elements.
struct NODE{ struct NODE *Succ; struct NODE *Prev; }; struct LIST{ struct NODE *Head; struct NODE *Tail; int count; }; struct LIST MyList; struct NODE FirstNode; struct NODE SecondNode; main() { struct LIST *List; struct NODE *N; // init nodes and list FirstNode.Succ = &SecondNode; FirstNode.Prev = 0; SecondNode.Succ = 0; SecondNode.Prev = &FirstNode; MyList.Head = &FirstNode; MyList.Tail = &SecondNode; MyList.count = 2; List = &MyList; // loop over all nodes for(N = List->Head;N;N = N->Succ) { } }
the side effect of N = N->Succ; is that the compiler think about the statement as follow: List->Head = List->Head->Succ; What on earth made you believe that? N is a copy of List->Head, not an alias, so further modifications to N will not modify List->Head at all. You seem to be in serious need of a re-visit to your C textbooks to understand what pointers are, and how they work.
I found that N and List is located in the same memory address(D:0x01) because List is no longer used after
N = List->Head
List-Head = (void*)0;
Have you checked the memory address in the map-file?? I tried different settings (SMALL/LARGE memory model, Optimization level 0 and 8, Linker LX51/BL51,...) but N and List were NEVER located on the same memory address !!!!!
I tried two different settings (using optimization level 0 and 8)under Large Memory Model,When using level 8,N and List were located in the same memory address,but when level 0,they weren't. Level 8:
SYMBOL TABLE OF MODULE: test (MAIN) VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- MAIN 0200000EH PUBLIC XDATA --- SecondNode 02000006H PUBLIC XDATA --- MyList 02000000H PUBLIC XDATA --- FirstNode 01000003H PUBLIC CODE --- main 01000003H BLOCK CODE --- LVL=0 00000001H SYMBOL DATA --- List 00000001H SYMBOL DATA --- N --- BLOCKEND --- --- LVL=0
SYMBOL TABLE OF MODULE: test (MAIN) VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- MAIN 0200000EH PUBLIC XDATA --- SecondNode 02000006H PUBLIC XDATA --- MyList 02000000H PUBLIC XDATA --- FirstNode 01000003H PUBLIC CODE --- main 01000003H BLOCK CODE --- LVL=0 02000014H SYMBOL XDATA --- List 02000017H SYMBOL XDATA --- N --- BLOCKEND --- --- LVL=0
Ok, I stripped down the code: optimization level 8, large (code/data), generic 8051 device
struct NODE{ struct NODE *Succ; struct NODE *Prev; }; struct LIST{ struct NODE *Head; struct NODE *Tail; int count; }; main() { struct LIST *List; struct NODE *N; // loop over all nodes for(N = List->Head;N;N = N->Succ) { } }
VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- MAIN 0100004AH PUBLIC CODE --- main 0100004AH BLOCK CODE --- LVL=0 0100004AH BLOCK CODE NEAR LAB LVL=1 02000000H SYMBOL XDATA --- List 00000001H SYMBOL DATA --- N --- BLOCKEND --- --- LVL=1 --- BLOCKEND --- --- LVL=0
I'm baffled as to why "List" seems to be being placed in xdata in your map file. If I compile this code in the small memory model, all variables are placed in DATA. List and N are placed at the same address, however I think this is because N is never used in the code hence it doesn't matter where it is placed: struct NODE{ struct NODE *Succ; struct NODE *Prev; }; struct LIST{ struct NODE *Head; struct NODE *Tail; int count; }; struct LIST MyList; struct NODE FirstNode; struct NODE SecondNode; main() { struct LIST *List; struct NODE *N; // init nodes and list FirstNode.Succ = &SecondNode; FirstNode.Prev = 0; SecondNode.Succ = 0; SecondNode.Prev = &FirstNode; MyList.Head = &FirstNode; MyList.Tail = &SecondNode; MyList.count = 2; List = &MyList; // loop over all nodes for(N = List->Head;N;N = N->Succ) { } } VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- JUNK 00000016H PUBLIC DATA --- SecondNode 00000010H PUBLIC DATA --- FirstNode 00000008H PUBLIC DATA --- MyList 01000003H PUBLIC CODE --- main 01000003H BLOCK CODE --- LVL=0 00000001H SYMBOL DATA --- List 00000001H SYMBOL DATA --- N 01000003H LINE CODE --- #44 01000003H LINE CODE --- #45 01000003H LINE CODE --- #50 0100000CH LINE CODE --- #51 01000015H LINE CODE --- #52 0100001EH LINE CODE --- #53 01000027H LINE CODE --- #54 01000030H LINE CODE --- #55 01000039H LINE CODE --- #56 0100003FH LINE CODE --- #58 01000045H LINE CODE --- #61 0100004BH LINE CODE --- #62 0100004BH LINE CODE --- #63 0100004FH LINE CODE --- #65 --- BLOCKEND --- --- LVL=0 However, if I initialise N: struct NODE{ struct NODE *Succ; struct NODE *Prev; }; struct LIST{ struct NODE *Head; struct NODE *Tail; int count; }; struct LIST MyList; struct NODE FirstNode; struct NODE SecondNode; main() { struct LIST *List; struct NODE *N; // init nodes and list FirstNode.Succ = &SecondNode; FirstNode.Prev = 0; SecondNode.Succ = 0; SecondNode.Prev = &FirstNode; MyList.Head = &FirstNode; MyList.Tail = &SecondNode; MyList.count = 2; List = &MyList; N=&FirstNode; // loop over all nodes for(N = List->Head;N;N = N->Succ) { } } VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- JUNK 00000016H PUBLIC DATA --- SecondNode 00000010H PUBLIC DATA --- FirstNode 00000008H PUBLIC DATA --- MyList 01000003H PUBLIC CODE --- main 01000003H BLOCK CODE --- LVL=0 0000001CH SYMBOL DATA --- List 00000001H SYMBOL DATA --- N 01000003H LINE CODE --- #44 01000003H LINE CODE --- #45 01000003H LINE CODE --- #50 0100000CH LINE CODE --- #51 01000015H LINE CODE --- #52 0100001EH LINE CODE --- #53 01000027H LINE CODE --- #54 01000030H LINE CODE --- #55 01000039H LINE CODE --- #56 0100003FH LINE CODE --- #58 01000048H LINE CODE --- #59 01000048H LINE CODE --- #61 01000054H LINE CODE --- #62 01000054H LINE CODE --- #63 01000058H LINE CODE --- #65 --- BLOCKEND --- --- LVL=0 Stefan
List is placed in XDATA because I use the large memory model (see message)... "N is never used in the code hence it doesn't matter where it is placed: " N is used in code: "N = List->Head" and "N = N->Succ" in the for-loop. In small model I get the following map-file:
VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- MAIN 01000003H PUBLIC CODE --- main 01000003H BLOCK CODE --- LVL=0 01000003H BLOCK CODE NEAR LAB LVL=1 00000008H SYMBOL DATA --- List 00000001H SYMBOL DATA --- N --- BLOCKEND --- --- LVL=1 --- BLOCKEND --- --- LVL=0
You were looking for the wrong kind of symptoms, then. The fact that two variables end up being placed in the same address, all by itself, tells you exactly nothing about the actual behaviour of the program. The compiler is perfectly allowed to re-use the memory positions used for 'List' to store something else in it after 'List' itself is no longer used. That's what the word "optimization" in "optimization level 8" is mainly about, after all. Without this kind of tricks, it would be close to impossible to fit any decent-sized C program into a typical 8051 device --- there simply isn't enough memory space to spare.
"List is placed in XDATA because I use the large memory model" Ok, but shouldn't N therefore be placed in xdata as well? Quoting from your map file above: 02000000H SYMBOL XDATA --- List 00000001H SYMBOL DATA --- N "N is used in code: "N = List->Head" and "N = N->Succ" in the for-loop" Yes, I must have been sleeping. Again. I think Hans is right, the optimisation is legitimately causing this. The order of events is (pseudocode): List=An address; N=List->Head; LABEL: N=N->Succ; if(N) goto LABEL So, List and N can occupy the same location without anything going wrong. Stefan