Reputation: 1457
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
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
CERT recommend against them from a security perspective.
Upvotes: 0
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
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.
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.
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.
Can a conforming C implementation #define NULL to be something wacky
has fun explanation of notions.
Upvotes: -1
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
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