modest
modest

Reputation: 1457

What is the correct return type for C function which returns different data types

I was once asked to write a function which will return a pointer to some data in the memory upon some successful condition else it should return "-1". In this case, what would be the correct return type. If I only had to return the data then I would have char * as the return type of the function myfunction. But in this case, I may return -1 has return type.

<what-type> myfunction() {

char *data;

if (some condition true)
  return data;
else 
  return -1
}

int main () {

 myfunction

}

Upvotes: 4

Views: 1977

Answers (5)

hlovdal
hlovdal

Reputation: 28198

function which will return a pointer .. upon some successful condition else it should return "-1".

Do yourself a favour and do not mix error indication and function result into one object like that. Split them out in two distinct entities by letting the function just return a boolean success indicator, and return the actual result data though a pointer like

bool myfunction(char **result_ptr) {
        char *data;

        if (some error condition)
                return false;

        *result_ptr = data;
        return true;
}

int main () {
        bool success;
        char *data:

        success = myfunction(&data);
        if (success)
                use(data);

}

In-band error indicators makes poor APIs that often invite failures (in the extreme case of the realloc function, it begs you to write code that looses the original pointer in case of failure), and it fails at least the following Characteristics of a Good API

  • Easy to use, even without documentation
  • Hard to misuse
  • Easy to read and maintain code that uses it

CERT recommend against them from a security perspective.

Upvotes: 0

Daemon
Daemon

Reputation: 1675

If not using NULL, then you can typecast the return value

char* myfuntion(){  
                return (char*)-1;
}
int main () {
 printf("%d",myfuntion());
}

Upvotes: -1

Ahmed Masud
Ahmed Masud

Reputation: 22382

It is possible to cast -1 to void * and check for it. you can return ((void *)-1); Note that there is no notion of signed-ness of pointers in C.

If you think that it feels a bit crazy :-) you're probably right. But there are instances where this convention may be useful for error handling. And there are uses of it out there in important projects. In particular implementations of pthread library use this convention at times.

Can a pointer (address) ever be negative?

Has a great deal to say about it.

On the notion of special interpretations of pointers by their value.

Okay so there seems to be some issue about how guarantees that (void*)-1 is NOT an actual pointer. and @ictoofay seems to think that somehow I mentioned a guarantee about (void *)-1 above and how it cannot be a valid address, which I would like to clarify that I didn't.

Having said that, assuming that a system that uses direct memory mapping and not virtual addresses. (void *)-1 would be the very last address in that model, and in the strictest sense you shouldn't use it. However, you can make assumptions about the storage capacity of the last physical address (see ldl example below)

But the notion of "special" interpretation to of pointers by examining there value in real life projects is not new. Actually, it is a notion USED in most modern operating systems when they do memory address management. It is quite common that a system will use addresses and address ranges and use them for "special meaning". So in reality, you as a programmer ARE actually free to make whatever assumptions and live with their consequences. The notion that (void *)-1 can be used as a special value is not far fetched. Note that this still does NOT say anything about the (in?)compatibility of the notion with the fact that (void *)-1 could be a valid address in a given case.

Now for addressing this "crazy" notion and why would any one use. Here are two real life examples of where (void*)-1 is being safely.

pthreads uses it on Linux, HPUX, solaris and most BSDs.

In particular PTHREAD_CANCELED is a ((void *)-1)

From pthread.h

#define PTHREAD_CANCELED ((void *) -1)

It's defined as ((void *)1) in the darwin version of the pthread libraries. Fun fun;

In glibc (with _GNU_SOURCE defined), ld.so provides the ability to search for alternate value of the same symbol in dynamically loaded libraries. There the value for RTLD_NEXT is (void *)-1.

A thought on fluidity of C

In C is no reason why a given value has to be interpreted in a particular way. C is not strictly typed and is fluid in these notions. A LOT of its power comes from that.

On 'value' of NULL

Can a conforming C implementation #define NULL to be something wacky

has fun explanation of notions.

Upvotes: -1

Ed Heal
Ed Heal

Reputation: 60007

Use union and perhaps define a typedef for it.

i.e.

typedef struct {
   int is_error;
   union {
     int error_code;
     char *data;
   }
} ReturnType;

Then

ReturnType myFunction(....) { ... etc }

The caller can check if the function is error (get a return error code) or get the data otherwise.

Upvotes: 7

Alok Save
Alok Save

Reputation: 206546

If you want to return different data types, Use a void*:

void* myfunction();
^^^^^

In your case returning a NULL seems to be the more ideal solution rather than the -1.
It will allow users of your function to write code such as:

if(myfunction())
{
    //Utilize the returned string
}

Upvotes: 4

Related Questions