About the return value of C's self-made function

Asked 2 years ago, Updated 2 years ago, 36 views

Sorry for the new question.

If you created your own function in C,
I can't decide what to return with the return value.

If the return type is int type,
Should I return -1 or 0 in case of an error?

Also, if you set the return value type to char* equal pointer type,
Should I return an empty pointer in case of an error?

Other than the above,
Please give us your advice and feedback.

c

2022-09-30 20:45

10 Answers

If the return type is int type,
Should I return -1 or 0 in case of an error?

In any case, it's important to be consistent.

If you use it with other libraries and the library consists of functions that return 0 as an error, you can reduce confusion by matching your own functions (for consistency).

However, when combined with multiple libraries, if one library has a 0 error and the other has a -1 error, it is not consistent.

In this case, it is recommended that you write the error in a way that is easy to understand.

if(val<10){
    return 0;
}

The code does not tell if return0 is successful or abnormal.

So,

if(val<10){
    return NO_ERROR;
}

Yes

if(val<10){
    return ERR_OUT_OF_RANGE;
}

If you write like this, it will be easier to read the source in the future.


2022-09-30 20:45

For your information.

If the return type is a function of int, I think you chose int because you want to return a number.It's the number of themselves.The current value.

If it is an error, then if the return value of the function returns a value that is clearly not appropriate (for example, -1 or 0, you or others who call it will notice that it is an error.I think it's better to choose a value like that.

-1 or 0 (or any other value) is case-by-case, so select according to what the return value of the function means.For example, is it possible to get 0
値 Regarding the selection of values, I think the return value of the standard function is very helpful, so I think it would be interesting to look at the standard function from that perspective.

If you clearly define that the return value (for example, -1) is an error value rather than the same, the caller will be even happier.

#defineFUNCXXX_ERROR(-1)

intFunc(void){
    intret = 0;
    if(/*Error Determination*/)
        return FUNCXXX_ERROR;
    }
    /* Normal Time Processing*/
    return;
}

and so on, enum instead of define.
You can't decide whether the returned -1 is an error or a normal value.
Also, if you want to change the error value that this function represents (for example, -1 has since been included in the normal value), you only need to change the definition value of define.

As for the char* type, I think it's almost an option to return NULL.
上記There may be cases where you define a value that is clearly incorrect as mentioned above.

Even if you take a simple "mold," it can have many meanings.
Select the error value to match the meaning and "design" the function.


2022-09-30 20:45

Typically, the return value of a function with a return value can be either a value or a meaning.
If you say int, the return value is only an integer.
For example, if you want to return the meaning, you can use

typedefenum CALL_SATUS// Results
{
  CALL_SATUS_OK, // Successful
  CALL_SATUS_INVALID_PARAM, // argument incorrect
  CALL_SATUS_ERR, // Other Errors
} CALL_SATUS

CALL_STATUS MyFunction()
{
  CALL_STATUS Stat;  
  :// the process of something.assessment of results
  Return Stat;//CALL_SATUS type returns meaning
}

The code may be similar to the one shown in .


2022-09-30 20:45

If you talk about this, it may only make it unnecessarily complicated and interfere with your understanding, but I would like to explain to you that practical programs often have functions that produce errors like this.
In addition to the function return value, use the pointer argument to issue an error message.

Sample: Functions that Returns Surplus

#include<stdio.h>

enum ERROR {NOERROR=0,ZERODIVIDE};
// After zero division, ZERODIVIDE
int surplus(inta, intb, enum ERROR* error){
// a: divisor, b: divisor, error: error message
    if(b==0){// If the divisor is 0
        * error = ZERODIVIDE;
        return 0;
    } else{
        * error = NOERROR;
        return a %b;
    }
}

int main() {
    intx = 100; // Change the value as appropriate.
    inty=0;// Change the value as appropriate.
    enum ERROR err = NOERROR;

    int result=surplus(x,y,&err);

    if(err==ZERODIVIDE) {// after zero division
        printf("Divid by 0\n";
    } Else {// Output surplus if error does not appear
        printf("Surplus=%d\n", result);
    }

    return 0;
}

As an inverse pattern, there is also a function that uses the return value as an error message and passes the result by pointer argument.


2022-09-30 20:45

C languages after C99 are compatible with bool type, so

#include<stdbool.h>

You can use the bool type by reading in .

Also, the macro defines false as 0 and true as 1


2022-09-30 20:45

In the library, arguments are said to have no law, but returns have some law.Therefore, it is recommended that you match the library provided in c.For standard C libraries,

Returns 0 if the operation is completed within the function (success or failure) and a number such as any other or error number if it fails.

Example: socket(NULL, NULL, NULL); returns -1, error number 97.

Returns 0 or NULL upon failure if the operation is not completed within the function (requesting the function).

Example: fopen(", "r"); Error number 2
for(;malloc(long);)Error number 12

The error number is a value of errno.Typically, if a 0 error occurs, a value indicating the error is substituted.


2022-09-30 20:45

I feel that the answers so far are too biased toward int, so I will present a double case

If double log (double), the definition of natural logarithms for real numbers is
- For non-negative numbers, there can be any return value from negative infinity to positive infinity.
Therefore, it is impossible to express an error with a return value in the first place.
Therefore, the log() value range error is to return the value EDOM to errno.
The same situation may occur with the functions you create.

So, as you have already pointed out,
- How to implement it depends on the case.
- It's designed to think about it
- You should keep the design consistent within your scope of responsibility within one project.
That's it.

Java and others have been implemented with inspection exceptions, but this time it's C, so
There is no tacit understanding of language culture,
I can decide for myself. [Necessary] I guess.


2022-09-30 20:45

Both 0 and -1 are reasonable ints, so basically you can't think of "error if it's -1" as a function that returns ints.
What should I do?

First of all, it is better to create a function that does not cause an error condition.
If it is difficult, consider the following.

This is what 1 looks like:

int main (void) 
{
    int calc_result = 0;
    pool calc_validity=false;

    calc_validity=calculate(&calc_result);

    printf("Calculation result:%d, validity:%d", calc_result, calc_validity);
}

bool calculate(int*return_value) 
{
    int result = 1+1;
    *return_value=result;
    return(result==2) ?true:false;
}

For 2, this is what it looks like:

typedef structure calculation_result{
    bool valid;
    int result;
} calculation_result;

calculation_result calculate();

int main (void) 
{
    calculation_result result;

    result=calculate();

    printf("Calculation result:%d, validity:%d", result.result, result.valid);
}

calculation_result calculate()
{
    int result = 1+1;
    bool valid=(result==2) ?true:false);

    calculation_result return_value;
    return_value.valid=valid;
    return_value.result=result;

    return_value;
}

2 is easier to read, more generic, and there seems to be no problem with the pointer, so I recommend 2 somehow.
The code uses bool, so if you want to build with plain C compiler, map bool to char.


2022-09-30 20:45

The answer is "depending on how you designed it" as already mentioned.

Rice cake is a rice cake shop.Error is an error function.
In C language, errno.h is familiar, but errno.h is too system-defined.
Of course, I would like you to check errno as well.While acknowledging that it is not a pure C, let's take a look at the HRESULT type (typedef long type) used in Microsoft COM, etc. as a reference. http://www.carrona.org/winerror.html

Hmm. You've packed a lot of information into 32 bits.
I mean, it's packed too much. http://ir9.jp/prog/ayu/win32err.htm

In the case of HRESULT, it seems to be determined by the top two bits... but the important thing is to be "consistent" as SevenOfNine has already answered.In other words, we create error code definitions and decision macros through HRESULT so that anyone can handle them.

res=func(...);
if(result<0){...}

More than

 if (FAILED(res) {...} 

It's healthier like this (even if there's a change in the error design).The newly defined res value should return the decision in the FAILED macro.)


2022-09-30 20:45

There may be various design policies, but
Personally, I don't like to give two meanings to the return value.
There are many things like that in the standard library.For example,

FILE*fopen(const char*path, const char*mode); 

Return value is pointer on success and NULL on failure.

float strtof(const char*nptr, char**endptr); 

In this case, the return value cannot determine success/failure, so
You need to check if the errno in the global variable is a non-zero value.

It's kind of disgusting to have these kinds of things mixed together^^;

In my case, it is consistent to return only the success or failure of the process.


2022-09-30 20:45

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.