Still not "getting" pointers...
Geeky1
University of the Pacific (Stockton, CA, USA)
I understand what they are (I think), but I'm not understanding when they're supposed to be dereferenced and such.
I've finally finished this lab, and I have it working. BUT, the lab is supposed to be using pointers. After trying to get it working with pointers, I simply wrote it without them. The idea being that I can now go back and convert it to use pointers. Unfortunately, that's easier said than done. I still have no idea what the hell needs to be dereferenced, what doesn't, etc.
Here's the lab, if you want to take a look at it:
I've finally finished this lab, and I have it working. BUT, the lab is supposed to be using pointers. After trying to get it working with pointers, I simply wrote it without them. The idea being that I can now go back and convert it to use pointers. Unfortunately, that's easier said than done. I still have no idea what the hell needs to be dereferenced, what doesn't, etc.
Here's the lab, if you want to take a look at it:
0
Comments
Generally, you deref pointers when code moves BEYOND thier probable scope of use. Pointers for a module get dereffed after code has past them if no loopbacks in code, OR, when the module exits. Reason is to free up the naming stack for entry points as much as possible. When a pointer is actively in use, you keep its ref in pointer stack space.
The smaller the stack, the less the RAM load overall for module, to a small degree. So, cleanup is nice. what most folks do is this:
Module entry.
Clear var space.
Housekeeping, set up internal to module ref pointing stack. housekeeping, establish and initialize vars.
Process\WORK code.
Housekeeping, clear var stack of unneeded vars, IE vars not passed to other module being called. Housekeeping, deref pointers internal to module unless you have something like a dll structure where you keep the pointer stack up for that dll until dll is closed fully (dlls can have named or explicit entry points).
VAR pointers are cleared when the var stack is, only those parts cleared are dereferenced, pass-along vars have ref points kept until received by new module getting them. Most programming languages keep old pointers up for passed vars, in essence rereferencing them. So module passing them keeps them open.
This is just modulars, not container rules nor CLASS rules. CLASS pointing, so long as CLASS is active, CLASS pointers stay ref'd. Containers can have classes and transitory modules inside them, module and class rules followed as long as open in container. Destroy container, you implicitly destroy its refs as far as the container code is concerned, but it is nice to free RAM before destruct explicitly by destroying pointers as part of housekeeping just before container destruct. Not all compilers gen code to free RAM right unless you explicitly do this. Easier rule, do it always-- you will get less bug-bitten by compiler bugs.
Cliff's Notes version.
John D.
Ok, mostly modules. Ancient ANSI C had little continer stuff, limited classes.
So, you deref on exit pointers used only by module unless you have to free RAM for something as module works. var names ditto unless you are passing to aparent or child process some variables. If child is receiver, might as well keep pointers all open until you exit parent. If parent is receiver, all but the pass-along vars get derefed very close to pass-along time, typically. Some times folks will use an iterative submodule call loop. Then you might keep the submodule (child module) stack open also.
But, if parsing is straight through and should be one time, deref modules' owned vars and internal jump pointers for named jumps and then close.
Late C, C++, will use containers and CLASSES more (C will mostly use CLASS structure instead of container except one global container-like CLASS can be defined). Containers are mostly GUI environment stuff, Windows, KDE, Gnome, all use containers for GUI and KDE can contain apps as containers.
John D.
When process focus exits perview of module, all module-specific pointers that are also module-unique should already be deref'd. IF module eats so much stack space or RAM that it overflows stack space, then you get to deref what you will not agin use, on the fly to keep stack from overflowing. What no longer has to be ref'd is reference-killed. Compiler will then free stack space unless compiler rules say YOU, the coder, have to do so.
When you get into optimizing at assembly level, killing pointers as soon as no longer needed will become a habit. BUT, that is a different ball game.
For you, one thing you might look at is how to Data Flow Diagram info flows first, design process blocks logically with DFDs, then build Process Control flow charts. Use Process Control charting that you grok best. Then build modules that fulfill each control block and do the part that the DFD says needs to happen.
Essentially you kill workspace as process exits or before, deref is part of the workspace kill. You ref at need to limits of stack holding refs. Overflow the stack at your process's peril, it probably will abend or not compile if the compiler is in STRICT mode. Handle refs strictly for stack safety as far as housekeeping goes.
I used Assembly, C, BASIC (compiled and interpreted) and COBOL and Visual Basci and did DB programming(Paradox, FoxPro, some Access, and DBII), but learning COBOL taught me my most remembered lessons in strictness for VARs and pointers. Doing COBOL at process streaming level forced me to learn DFD and Control Charting, but the core of process focus was taught by DFDs and havign some good software engineers critique the heck out of DFDs first. DFDs are gross LOGICAL process tree designs. Control Flow Diagrams integrate in the compiler restrictions as to how process call each other. Then you code knowing beforehand what modules have to do in relation to each other.
John D.
Dereferencing a null pointer happens when you've got a pointer that isn't pointing at anything (0x000000) and you attempt to reference data from that pointer. Generally speaking, dereferencing a null pointer is a bad thing; it will cause a run-time error.
You reference a pointer like this: Where data is some variable, *data is the pointer to that variable, and *data-> is referencing the original variable from its pointer.
If you're trying to implement a linked list, I'd do this: Congratulations. You just implemented character strings as a linked list. I mentioned this in a code comment, but if you just set first to 0 and not actually delete each node, all the memory in your linked list isn't returned to the system at the end of execution.
If you bug me a bunch I can go find my all my source code from high school. It's in a .zip file on my IBM PC300GL (Pentium 1) and 120 miles away, so it may take some time to get.
-drasnor
-drasnor
Ok, well here's the source so far. It compiles and runs, but it doesn't print the data to a file- it prints the header, but none of the data.
Anyone care to take a look at it and tell me what I'm doing wrong?
I understand that * and & cancel each other out, but I don't really understand where they're supposed to be used. I do know that you need *s in the function prototypes. But beyond that, I have basically no idea what I'm doing.
For example, say I want to make a pointer to an integer; ptrNum and Num;
the code would be:
int Num;
int *ptrNum;
but would it then be:
"ptrNum = &Num;" or would it be "*ptrNum = &Num;" or "*ptrNum = Num;"?
What about for scanf? Since the & and * cancel each other out, it would just be "scanf("%d", ptrNum);" right?
Basically that's the problem I'm having. I just don't know when to dereference them, when not to, etc.
Many people get confused. That's why many people avoid pointers like the plague.
I'll explain.
You have demonstrated you know how to create a pointer.
< type >* nameOfPointer;
eg:
int* ptrNum;
That's the first step!
Now, knowing when to use * or & or neither . . .
Use * (de-referencing operator) to get the value of the pointer.
Think of it like this.
int Num;
int* ptrNum;
Say that Num is at address 56 and that ptrNum is at address 57. What is stored in address 57 is not a VALUE but a POINTER to another address.
ptrNum = &Num;
That assigns address 57 the POINTER of 56 (56 is the address of Num, and we know ptrNum now points to Num because &Num means "get me the address of Num"). Think of &< variable > in terms of a function: getAddressOf(variable);
Does that make it easier? Likewise, think of *< pointer > as a function: getValuePointedTo(pointer);
So, if you see "ptrNum" in code, what you're going to get is the POINTER, not WHAT IS POINTED TO.
eg:
int Num = 5;
int* ptrNum;
ptrNum = &Num;
Now, if I have: printf("Num = %d, ptrNum = %d\n", Num, ptrNum);
I will get printed: Num = 5, ptrNum = 56
However, if I want to get WHAT IS POINTED TO, I'll de-reference the pointer.
eg: printf("Num = %d, ptrNum = %d\n", Num, *ptrNum);
I will get printed: Num = 5, ptrNum = 5;
If I want the LOCATION (the address) of the variable/pointer, I will use &.
eg: printf("Num is located at %d, ptrNum is located at %d\n", &Num, &ptrNum);
I will get printed: Num = 56, ptrNum = 57;
Use scanf("%d", &Num); (where Num is an int, not a pointer to an int).
Hopefully this has helped you.