Still not "getting" pointers...

Geeky1Geeky1 University of the Pacific (Stockton, CA, USA)
edited March 2004 in Internet & Media
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:

Comments

  • Straight_ManStraight_Man Geeky, in my own way Naples, FL Icrontian
    edited March 2004
    What language are you using???

    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.
  • Geeky1Geeky1 University of the Pacific (Stockton, CA, USA)
    edited March 2004
    It's C. Not C++, just regular old ANSI C.
  • Straight_ManStraight_Man Geeky, in my own way Naples, FL Icrontian
    edited March 2004
    Geeky1 wrote:
    It's C. Not C++, just regular old ANSI C.

    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.
  • Straight_ManStraight_Man Geeky, in my own way Naples, FL Icrontian
    edited March 2004
    Think of focus:

    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.
  • drasnordrasnor Starship Operator Hawthorne, CA Icrontian
    edited March 2004
    Geeky is talking about a different kind of pointer (not an instruction or stack pointer). The pointer he's referring to is the kind that points to locations in memory (RAM) where data is stored. In other words, if I run a C++ code snippet like so:
    int data=1;
    cout<<*data;
    
    the output will be the hexadecimal address for the location in memory of the variable 'data'. I'm betting Geeky is taking high school Computer Science and they're learning C++ as a first computer language, since I just had two years of it and this is what they taught.

    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:
    int data=1;
    cout<<*data->;
    
    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:
    typedef *node ptr;
    struct node
    {
    	char data;
    	ptr next;
    };
    
    void main()
    {
    //This initializes the linked list.
    	ptr first, temp;
    	first=new node;
    	temp=first;
    	cin.get(first->data);
    //This will get characters from the console until you type a zero and hit return and store them into successive nodes in a linked list.
    	while(temp->data!='0')
    	{
    		temp->next=new node;
    		temp=temp->next;
    		cin.get(temp->data);
    	}
    //This will read out the contents of the linked list.
    	temp=first;
    	while(temp!=0)
    	{
    		cout<<temp->data;
    		temp=temp->next;
    	}
    //This will delete the linked list. Note that just setting first to zero creates a memory hole in your software.
    	temp=first;
    	while(first!=0)
    	{
    		first=first->next;
    		delete temp;
    		temp=first;
    	}
    }
    
    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 :fold:
  • drasnordrasnor Starship Operator Hawthorne, CA Icrontian
    edited March 2004
    Pfft. You're doing C, that's in C++. Just change the cout<< to printf and cin.get to scanf. Everything else is the same.

    -drasnor :fold:
  • t1rhinot1rhino Toronto
    edited March 2004
    Beware of pointers... They can cause leaky programs. :D
  • Geeky1Geeky1 University of the Pacific (Stockton, CA, USA)
    edited March 2004
    thanks :)

    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. :confused:

    Anyone care to take a look at it and tell me what I'm doing wrong?
  • a2jfreaka2jfreak Houston, TX Member
    edited March 2004
    Just got home about 30 mins ago. I'll try to take a look at it w/in the next hour or so and with any success I'll have the problem solved before 10p or 11p your time, Geeky.
  • a2jfreaka2jfreak Houston, TX Member
    edited March 2004
    Ok, I looked @ it (actually, I just stayed at the keyboard rather than go get a bite to eat like I was planning). Where I added code you'll see your original with a //a2jfreak comment in front of it, and then the line below that is the corrected code. (I didn't //a2jfreak comment out the inclusion of the debug header, I just // commented that out.)
  • Geeky1Geeky1 University of the Pacific (Stockton, CA, USA)
    edited March 2004
    Great, thanks! One other thing. The main issue I'm having with pointers is that I have no idea when to use *, &, or neither.

    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.
  • a2jfreaka2jfreak Houston, TX Member
    edited March 2004
    Geeky1 wrote:
    Great, thanks! One other thing. The main issue I'm having with pointers is that I have no idea when to use *, &, or neither.

    Many people get confused. That's why many people avoid pointers like the plague.
    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.

    I'll explain.
    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;"?

    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;

    What about for scanf? Since the & and * cancel each other out, it would just be "scanf("%d", ptrNum);" right?

    Use scanf("%d", &Num); (where Num is an int, not a pointer to an int).
    Basically that's the problem I'm having. I just don't know when to dereference them, when not to, etc.


    Hopefully this has helped you.
Sign In or Register to comment.