-3

I'm wanting to pass a local variable within a function, back through it's pointer parameter (not returned).

My assignment uses a stack data structure, and one criteria that must be used is the Pop() function must have a pointer parameter that is used to return the top-most item on the stack. I have used this before. My program became more complex with a data struct, I started getting either segmentation faults, or the data not being saved after the function's frame popped.

// Definitions
typedef char * string;
typedef enum { SUCCESS, FAIL } result;
typedef enum { INTEGER, DOUBLE, STRING } item_tag;


// Result Check
static result RESULT;


// Item_Tag
typedef struct {
    item_tag tag;
    union {
        int i;
        double d;
        string s;
    } value;
} item;

// Declarations
int STACK_SIZE = 0;
const int MAX_STACK_SIZE = 1024;       // Maximum stack size
item stack[1024];

// Pop
result Pop(item *ip){
    item poppedItem;
    item * pointerReturn = malloc(sizeof(item));

    // Check stack size is not 0
    if(STACK_SIZE == 0){
        return FAIL;
    }
        // If stack size is only 1, creates a blank stack
    else if(STACK_SIZE == 1){
        item emptyItem;
        // Initialize
        emptyItem.tag = INTEGER;
        emptyItem.value.i = 0;

        // Check top item's tag
        poppedItem = stack[0];
        // Store top item data based on tag
        switch(stack[0].tag){
            case STRING:
                poppedItem.value.s = stack[0].value.s;
            case DOUBLE:
                poppedItem.value.d = stack[0].value.d;
            default:
                poppedItem.value.i = stack[0].value.i;
        }
        poppedItem.tag = stack[0].tag;
        // Allocate memory for parameter, and have it point to poppedItem
        ip = malloc(sizeof(poppedItem));
        *ip = poppedItem;
        // Store empty stack to top of stack
        stack[0] = emptyItem;

        // Decrease stack size
        STACK_SIZE--;

    }
        // Grab top Item from stack
    else{
        // Check top item's tag
        poppedItem = stack[0];
        // Store top item data based on tag
        switch(stack[0].tag){
            case STRING:
                poppedItem.value.s = stack[0].value.s;
            case DOUBLE:
                poppedItem.value.d = stack[0].value.d;
            default:
                poppedItem.value.i = stack[0].value.i;
        }
        poppedItem.tag = stack[0].tag;
        // Allocate memory for parameter, and have it point to poppedItem
        ip = malloc(sizeof(poppedItem));
        *ip = poppedItem;

        // Reshuffle Items in Stack
        for(int idx = 0; idx < STACK_SIZE; idx++){
            stack[idx] = stack[idx + 1];
        }
        STACK_SIZE--;
    }
    return SUCCESS;
}

My knowledge with pointers is alright, and memory location/management. But I can't claim to be an expert by any means. I don't exactly know what happens in the background when you're using the function's own pointer parameter as a means of passing data back.

  1. What is the correct syntax to solve this problem?
  2. How can a parameter pass something back?

Thanks in advance!

EDIT* Since many people are confused. I'll post some snippets. This is an assignment, so I cannot simply post all of it online as that'd be inappropriate. But I think it's okay to post the function itself and have people analyze it. I'm aware it's a bit messy atm since I've edited it several dozen times to try and figure out the solution. Sorry for the confusion. Keep in mind that not all the code is there. just the function in question, and some of the structure.

  • 6
    Is it C or C++? Don't tag them both together. – iBug Dec 09 '17 at 14:28
  • 1
    You claimed that *your knowledge with pointers is alright*, but I don't think `catcher.variable` is written by someone sensible. Shouldn't `->` be used instead of the dot? – iBug Dec 09 '17 at 14:30
  • 1
    Adding to what @Ron has said, if you're learning C, you should take a look at this [C book like](/q/562303/5958455). – iBug Dec 09 '17 at 14:31
  • 1
    You need to use -> – Jake Freeman Dec 09 '17 at 14:31
  • Possible duplicate of [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – user0042 Dec 09 '17 at 14:32
  • C, sorry. Also, I'm aware that pointers use -> it was just a snippet to get the general idea across. @Ron I already have a C/C++ text. I'll bookmark it though. ty! – Sappharite Dec 09 '17 at 15:01
  • You have drastically modified the original code! You should not do that. Post the original code back and create a new question. – sg7 Dec 09 '17 at 15:23
  • @sg7 isn't that considered spam to repost a new topic when one already exists? – Sappharite Dec 09 '17 at 15:24
  • Not, if you drastically change the code! Otherwise your problem is a moving target and invalidates the previous responses. Mind other people efforts to help you! – sg7 Dec 09 '17 at 15:25
  • @sg7 I don't know how to undo an edit on here. Should i just delete this and repost? – Sappharite Dec 09 '17 at 15:26
  • I posted the original code. You can access your changes clicking on **edited xx mins ago** [link](https://stackoverflow.com/posts/47729573/revisions) – sg7 Dec 09 '17 at 15:33

2 Answers2

2

The function should receive a pointer to a valid object:

item catcher;
myFunc(&catcher);  // Pass a pointer to catcher

and the function should modify the object it received a pointer to:

void myFunc(item *itemPointer)
{
    itemPointer->variable = stuff;
    // or
    *itemPointer = someItem;
}

Update:

You're overcomplicating things immensely – there should be no mallocs when popping, and you're leaking memory all over the place.
(Your knowledge of pointers and memory management is far from "alright". It looks more like a novice's guesswork than knowledge.)

It should be something more like this:

result Pop(item *ip){
    if (STACK_SIZE == 0){
        return FAIL;
    }
    else {
        *ip = stack[0];
        for(int idx = 0; idx < STACK_SIZE; idx++){
            stack[idx] = stack[idx + 1];
        }
        STACK_SIZE--;
    }
    return SUCCESS;
}

but it's better to push/pop at the far end of the array:

result Pop(item *ip){
    if (STACK_SIZE == 0){
        return FAIL;
    }
    else {
        *ip = stack[STACK_SIZE-1];
        STACK_SIZE--;
    }
    return SUCCESS;
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • This was what I had tried before. The address of "someItem" is not saved once the function's frame stack is popped. Here's a readout from GDB right after Pop() is finished: <> (gdb) display topItem 1: topItem = {tag = INTEGER, value = {i = 0, d = 0, s = 0x0}} (gdb) display bottomItem 2: bottomItem = {tag = (unknown: 9242040), value = {i = 1, d = 4.9406564584124654e-324, s = 0x1 }}<> – Sappharite Dec 09 '17 at 15:07
  • I have modified the original post, and added portions of the code. – Sappharite Dec 09 '17 at 15:17
  • I'm terribly sorry for that. I have to be very careful with assignments and the university guidelines. My code is messy, yeah. Honestly, I was just confused when using parameter's as a means of returning or modifying something out of the function's scope. I apologize to everyone here. I have never used SOF as well, and I prob ticked most people off. – Sappharite Dec 09 '17 at 15:35
0

Response to the originally posted code:

typedef struct{
    variables
}item;

void myFunc(item *itemPointer){
    item newItem;
    newItem.variable = stuff;
}

int main(){
    item * catcher;
    myFunc(catcher);
    printf("%s\n", catcher.variable);
}

A few issues.

Your program will not compile. variable has to have a type.

void myFunc(item *itemPointer){
    item newItem;
    newItem.variable = stuff;
}

stuff is not defined; item *itemPointer is not used.

item * catcher pointer has to point to allocated memory. It is not initialized.

Pass arguments via pointers and modify member of the structure like this:

void myFunc(item *itemPointer, const char *string){

    itemPointer->variable = string ;
}

Solution like:

void myFunc(item *itemPointer)
{
    itemPointer->variable = stuff;
    // or
    *itemPointer = someItem;
}

is possible, but it assumes that stuff or someItem is a global variable which is not the best programming practice IMO.

Retrieve value from pointer via -> not . operator.

#include <stdio.h>
#include <stdlib.h>

typedef struct{
    char * variable;
}item;

void myFunc(item *itemPointer, const char *string){

itemPointer->variable = string ;
}

int main(){
    item * catcher;
    char *new_string = "new string";

    catcher = malloc(sizeof(item));

    myFunc(catcher, new_string);
    printf("%s\n", catcher->variable);
    free(catcher);
    return 0;
}

OUTPUT:

new string
sg7
  • 6,108
  • 2
  • 32
  • 40
  • I edited my original post and posted snippets of the code. Perhaps that'll help understand what's going on. – Sappharite Dec 09 '17 at 15:22