Pradeep Kumar
Pradeep Kumar

Reputation: 77

Confusion in the C code on returning a value

I have written a function that has a return type of ListEntry created with typedef as follows

ListEntry RetrieveList(Position p,List *list)
{   if(p<0 || p>=list->count)
   {    Error("Invalid Position");
    return;
   }
else{
    SetPosition(p,list);
    ListEntry x=list->current->entry;
    return x;
  }
}

It checks whether the position is valid or not. If the position is not valid I don't want to return anything from the function . Please Help !

Upvotes: 0

Views: 66

Answers (2)

ad absurdum
ad absurdum

Reputation: 21323

The RetrieveList() function, as defined, must return a ListEntry value. One possibility, without changing the function signature, is to choose a return value that can signal an invalid position condition. Since ListEntry is a typedef for int, according to OP comments, an integer value that can not represent a ListEntry could be chosen; perhaps -1:

ListEntry RetrieveList(Position p, List *list)
{   if (p<0 || p >= list->count) {
        Error("Invalid Position");
        return -1;
    } else {
        SetPosition(p, list);
        ListEntry x = list->current->entry;
        return x;
    }
}

Alternatively, you could change the function signature for RetrieveList() to return a pointer to ListEntry. Then a null pointer can be returned in the event of an invalid position condition. But, to make this work you need to have a ListEntry object for the returned pointer to point to. This can't be defined locally within RetrieveList(), since the lifetime of such local variables ends after the function has returned (making any pointers that point to them invalid). A ListEntry object could be allocated using malloc(), but then this object will need to be deallocated later:

ListEntry * RetrieveList(Position p, List *list)
{   if (p<0 || p >= list->count) {
        Error("Invalid Position");
        return NULL;
    } else {
        SetPosition(p, list);

        /* allocate a ListEntry object, but must remember to free() */
        ListEntry *x = malloc(sizeof *x);

        /* should also check that allocation was successful before using */
        *x = list->current->entry;

        return x;
    }
}

The above code should also check the value returned from malloc() to be sure that the allocation was successful. Instead of using malloc(), you could pass a pointer to a ListEntry object defined in the calling function. There is no need to remember to free() anything with this approach, but it may seem clumsy:

ListEntry * RetrieveList(Position p, List *list, ListEntry *lent)
{   if (p<0 || p >= list->count) {
        Error("Invalid Position");
        lent = NULL;
    } else {
        SetPosition(p, list);
        *lent = list->current->entry;
    }

    return lent;
}

This would be called like this:

ListEntry lentry;
if (RetrieveList(pos, list_ptr, &lentry) == NULL) {
    /* Handle invalid position */
} else {
    /* Proceed; lentry holds the value from list->current->entry */
}

I would probably go for the first option, since that is the most straightforward. Also, consider removing the typedefs, since these only serve to obfuscate the code; better to know what types are being used unless there is a good reason to hide this information.

Upvotes: 2

Pradeep Kumar
Pradeep Kumar

Reputation: 77

I have done it using pointer as follows

ListEntry *RetrieveList(Position p,List *list)
{   if(p<0 || p>=list->count)
{    Error("Invalid Position");
    return NULL;
}
else{
    SetPosition(p,list);
    ListEntry y=list->current->entry;
    ListEntry *x=&y;
    return x;
}
}

Upvotes: 0

Related Questions