从函数返回多个错误之一并用C语言结束程序的最佳实践是什么?
我找不到从函数中的函数返回错误并结束程序的方法 我曾考虑使用一个结构并将返回值存储在其中,然后以这种方式结束它,但我不知道这是否是最佳实践 假设我有这样一个程序:从函数返回多个错误之一并用C语言结束程序的最佳实践是什么?,c,C,我找不到从函数中的函数返回错误并结束程序的方法 我曾考虑使用一个结构并将返回值存储在其中,然后以这种方式结束它,但我不知道这是否是最佳实践 假设我有这样一个程序: int main() { // do stuff importantFunction(); // do stuff return 0; } 在importantFunction中,我调用了另外两个函数,它们正在进行一些位移位,并且总是返回一个数组。现在我想尝试返回1或0x01,因为如果此函数中的一个函数发生错误,该
int main()
{
// do stuff
importantFunction();
// do stuff
return 0;
}
在importantFunction中,我调用了另外两个函数,它们正在进行一些位移位,并且总是返回一个数组。现在我想尝试返回1或0x01,因为如果此函数中的一个函数发生错误,该函数将返回数组指针,但我不确定如何返回
char *importantFunction()
{
//do stuff
secoundFunction();
thirdFunction();
//do stuff
return array;
}
char *secoundFunction()
{
// do stuff
if (something == x)
return array;
// do stuff
return array;
}
我只是想找到一个方法,而不必检查第一个函数是否等于某个值,然后在int main中结束程序。
我试图避免这种情况,因为它并不总是起作用:
int main()
{
// do stuff
char *pointer = importantFunction();
if (*pointer == 'something')
return 1;
if (*pointer == 'something')
return 2;
if (*pointer == 'something')
return 3;
// and so on...
// do stuff
return 0;
}
如果这是一个愚蠢的问题,我很抱歉,我不太擅长提问。C中处理错误的一种常见方法是通过返回值 假设函数f成功返回指向字符串的指针
char *f();
此类函数在出现故障时将返回空指针,您可以通过包含一些常见头文件(例如)来获得空指针
现在假设g是一个函数,它给定一个整数,计算一些东西并返回运算的整数结果,但该函数可能会失败,例如,参数对计算无效,谁知道呢。。。。那也许你想这样写
int g(int i, int *result);
这里,i是用于计算某些内容的参数,result是指向将用于存储结果的变量的指针。为什么g的返回类型是int?好吧,它可以是bool,但通常是一个使用int。。。返回值将用作布尔值,g在失败时返回0,成功时返回1
可以在第三个函数h中这样使用这些函数
C中处理错误的一种常见方法是通过返回值 假设函数f成功返回指向字符串的指针
char *f();
此类函数在出现故障时将返回空指针,您可以通过包含一些常见头文件(例如)来获得空指针
现在假设g是一个函数,它给定一个整数,计算一些东西并返回运算的整数结果,但该函数可能会失败,例如,参数对计算无效,谁知道呢。。。。那也许你想这样写
int g(int i, int *result);
这里,i是用于计算某些内容的参数,result是指向将用于存储结果的变量的指针。为什么g的返回类型是int?好吧,它可以是bool,但通常是一个使用int。。。返回值将用作布尔值,g在失败时返回0,成功时返回1
可以在第三个函数h中这样使用这些函数
不要使用指针返回带外错误代码。指针无效时为NULL或有效,通常在程序中堆栈溢出。正在执行char*pointer=char*uintpttr_t1;这只是让人困惑,如果uintptr_tpointer==1{..}那么做同样是不可维护的 返回一个int。int在C标准库中通常用于返回错误。通常C库在出错时返回-1,设置errno-I通常编写返回负值的库代码,即在malloc失败时返回-ENOMEM。成功时返回0,可能返回正值以通知库中某些状态的用户代码。通过指针传递要设置的所有变量。看例句意见:不要使用fopen_s,只看它
enum importantFunction_rets_e {
IMPORTANT_FUNCTION_ERR_1 = -1,
IMPORTANT_FUNCTION_ERR_2 = -2,
IMPORTANT_FUNCTION_STATE_1 = 1,
IMPORTANT_FUNCTION_STATE_2 = 2,
};
int importantFunction(char **pointer)
{
assert(pointer != NULL);
// or maybe
if (pointer == NULL) return -EINVAL;
int ret;
ret = secondFunction(pointer);
if (ret < 0) return ret;
ret = thirdFunction(pointer);
if (ret < 0) return ret;
return 0;
}
int secondFunction(char **pointer) {
*pointer = malloc(sizeof(char) * 5);
if (*pointer == NULL) {
return IMPORTANT_FUNCTION_ERR_1;
}
memcpy(*pointer, "hey!", 5);
return 0;
}
int main() {
char *pointer;
const int importantFunction_ret = importantFunction(&pointer);
if (importantFunction_ret < 0) {
if (importantFunction_ret == IMPORTANT_FUNCTION_ERR_1) {
// handle err 1
} else if (importantFunction_ret == IMPORTANT_FUNCTION_ERR_2) {
// handle err 2
} else {
// hanlde other errors
}
return -1;
}
if (importantFunction_ret == IMPORTANT_FUNCTION_STATE_1) {
// handle state1
} else if {importantFunction_ret == IMPORTANT_FUNCTION_STATE_2) {
// handle state2
} else {
// handle other states
assert(0);
}
}
如果您想探索C语言中的主题或错误处理,您可以实现新的还是旧的?使用与面向对象语言相同的方法使用std::variant或std::expected或类似的观点:我确实反对这个建议,因为它现在是这样,它需要重新设计/重构,但这将是C向前迈出的一大步。不要用指针返回带外错误代码。指针无效时为NULL或有效,通常在程序中堆栈溢出。正在执行char*pointer=char*uintpttr_t1;这只是让人困惑,如果uintptr_tpointer==1{..}那么做同样是不可维护的 返回一个int。int在C标准库中通常用于返回错误。通常C库在出错时返回-1,设置errno-I通常编写返回负值的库代码,即在malloc失败时返回-ENOMEM。成功时返回0,可能返回正值以通知库中某些状态的用户代码。通过指针传递要设置的所有变量。看例句意见:不要使用fopen_s,只看它
enum importantFunction_rets_e {
IMPORTANT_FUNCTION_ERR_1 = -1,
IMPORTANT_FUNCTION_ERR_2 = -2,
IMPORTANT_FUNCTION_STATE_1 = 1,
IMPORTANT_FUNCTION_STATE_2 = 2,
};
int importantFunction(char **pointer)
{
assert(pointer != NULL);
// or maybe
if (pointer == NULL) return -EINVAL;
int ret;
ret = secondFunction(pointer);
if (ret < 0) return ret;
ret = thirdFunction(pointer);
if (ret < 0) return ret;
return 0;
}
int secondFunction(char **pointer) {
*pointer = malloc(sizeof(char) * 5);
if (*pointer == NULL) {
return IMPORTANT_FUNCTION_ERR_1;
}
memcpy(*pointer, "hey!", 5);
return 0;
}
int main() {
char *pointer;
const int importantFunction_ret = importantFunction(&pointer);
if (importantFunction_ret < 0) {
if (importantFunction_ret == IMPORTANT_FUNCTION_ERR_1) {
// handle err 1
} else if (importantFunction_ret == IMPORTANT_FUNCTION_ERR_2) {
// handle err 2
} else {
// hanlde other errors
}
return -1;
}
if (importantFunction_ret == IMPORTANT_FUNCTION_STATE_1) {
// handle state1
} else if {importantFunction_ret == IMPORTANT_FUNCTION_STATE_2) {
// handle state2
} else {
// handle other states
assert(0);
}
}
如果您想探索C语言中的主题或错误处理,您可以实现新的还是旧的?使用与面向对象语言相同的方法使用std::variant或std::expected或类似的观点:我真的反对这个提议,因为它现在是这样,它需要重新设计/重构,但这将是一大步
对于C.有三种从函数返回错误的常见模式: 让函数返回一个int,具体值表示成功和失败 例如,从main返回EXIT_SUCCESS或EXIT_FAILURE是C标准建议报告整个流程成功或失败的方式。BSD变体试图标准化一些其他代码;如果您的系统有一个标题,您可以使用这些标题。但请注意,它们并不是标准的,只是我们最接近达成协议的一件事,即流程如何报告错误代码 为错误保留特定的返回值,并使用全局或线程局部变量(通常为errno)来描述错误 大多数标准C库函数都这样做,函数返回int时使用-1表示错误,函数返回指针时使用NULL表示错误 使用额外参数指向错误指示器 这种方法在从Fortran派生的代码和接口中很常见。通常,错误指示符是可选的,如果调用方对结果是否有效不感兴趣,则可能会将其保留为空 我自己的规则很简单: 在编写低级库时,首选第二种方法。对于熟悉标准C库的人来说,这是一种熟悉的方法 对可恢复的错误使用第一种方法 通常,我使用return 0将它与第二个结合起来;追求成功,回报错误;或返回errno=EINVAL;等等,以防出错。最后一个首先将EINVAL分配给errno,然后返回EINVAL 当错误状态应该在许多操作中保留,或者存在状态错误影响的结构时,请使用第三种方法 让我们看看这些方法在实践中有何不同 一件非常常见的事情是将命令行参数解析为数字。让我们看一个例子,在某种计算中,参数将用作双精度:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int arg;
double val;
for (arg = 1; arg < argc; arg++) {
if (sscanf(argv[arg], "%lf", &val) == 1) {
printf("argv[%d] = %.6f\n", arg, val);
} else {
printf("%s: Not a number.\n", argv[arg]);
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
这是可行的,因为sscanf返回成功转换的次数,我们只希望双转换%lf工作,而字符转换%c失败
不幸的是,scanf系列函数不检查溢出。如果你提供的数字足够大,它就会被悄悄地破坏。不好的。为了避免这种情况,我们可以使用strtod。为了简化使用,我们可以将它放在单独的函数parse_double中。但是,该如何返回值以及可能的错误?要执行以下哪一项
/* Convert the initial double, returning the pointer to the rest of the
string; or NULL if an error occurs. */
const char *parse_double(const char *src, double *to);
/* If the string contains exactly one double, convert it and return 0.
Otherwise return a nonzero error code. */
int parse_double(const char *src, double *to);
/* Convert the string to a double as best as you can. If an error occurs, return 'errval'. */
double parse_double(const char *src, const double errval);
那么,哪一个是最好的呢
答案当然是,这取决于用例
实际上,我已经在不同的程序中实现了这三个,这取决于哪一个是最合适的
当使用相同的函数来解析输入文件时,第一个函数特别有用,并且/或者我们允许每个参数/行有任意数量的双精度。它很容易在循环中使用
第二个是我在程序中最常用的。我经常使用
typedef struct {
double x;
double y;
double z;
} vec3d;
int parse_vector(const char *src, vec3d *to)
{
vec3d temp;
char dummy;
if (!src || !*src)
return -1; /* NULL or empty string */
if (sscanf(src, " %lf %lf %lf %c", &temp.x, &temp.y, &temp.z, &dummy) == 3 ||
sscanf(src, " %lf %*[.,:/] %lf %*[.,:/] %lf %c", &temp.x, &temp.y, &temp.z, &dummy) == 3) {
if (to)
*to = temp;
return 0;
}
return -1;
}
它允许在命令行上使用1+2+3、1/2/3、1:2:3甚至“1 2 3”或1 2 3指定3D向量。需要引号来阻止shell将其拆分为三个单独的参数。它不会检查双重溢出,因此在输出中显示已解析的向量非常重要,这样用户就可以检测到他们的输入是否有误
%*[,:/]中的星号*表示转换结果不存储在任何位置,并且转换不计入返回值。[是转换说明符,转换列表中的任何和所有字符,以]字符结尾。[^是相反的,转换列表中未包含的所有字符。函数返回错误有三种常见模式: 让函数返回一个int,具体值表示成功和失败 例如,从main返回EXIT_SUCCESS或EXIT_FAILURE是C标准建议报告整个流程成功或失败的方式。BSD变体试图标准化一些其他代码;如果您的系统有标头,则可以使用这些代码。但请注意,它们不是标准的,只是我们必须达成一致的最接近的一种方式说明进程如何报告错误代码 为错误保留特定的返回值,并使用全局或线程局部变量(通常为errno)来描述错误 大多数标准C库函数都这样做,函数返回int时使用-1表示错误,函数返回指针时使用NULL表示错误 使用额外参数指向错误指示器 这种方法在从Fortran派生的代码和接口中很常见。通常,错误指示符是可选的,如果调用方对结果是否有效不感兴趣,则可以将其保留为空 我自己的规则很简单: 在编写低级库时,首选第二种方法。这是熟悉标准C库的人所熟悉的方法 U se是可恢复错误的第一种方法 通常,我使用return 0将它与第二个结合起来;追求成功,回报错误;或返回errno=EINVAL;等等,以防出错。最后一个首先将EINVAL分配给errno,然后返回EINVAL 当错误状态应该在许多操作中保留,或者存在状态错误影响的结构时,请使用第三种方法 让我们看看这些方法在实践中有何不同 一件非常常见的事情是将命令行参数解析为数字。让我们看一个例子,在某种计算中,参数将用作双精度:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int arg;
double val;
for (arg = 1; arg < argc; arg++) {
if (sscanf(argv[arg], "%lf", &val) == 1) {
printf("argv[%d] = %.6f\n", arg, val);
} else {
printf("%s: Not a number.\n", argv[arg]);
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
这是可行的,因为sscanf返回成功转换的次数,我们只希望双转换%lf工作,而字符转换%c失败
不幸的是,scanf系列函数不检查溢出。如果你提供的数字足够大,它就会被悄悄地破坏。不好的。为了避免这种情况,我们可以使用strtod。为了简化使用,我们可以将它放在单独的函数parse_double中。但是,该如何返回值以及可能的错误?要执行以下哪一项
/* Convert the initial double, returning the pointer to the rest of the
string; or NULL if an error occurs. */
const char *parse_double(const char *src, double *to);
/* If the string contains exactly one double, convert it and return 0.
Otherwise return a nonzero error code. */
int parse_double(const char *src, double *to);
/* Convert the string to a double as best as you can. If an error occurs, return 'errval'. */
double parse_double(const char *src, const double errval);
那么,哪一个是最好的呢
答案当然是,这取决于用例
实际上,我已经在不同的程序中实现了这三个,这取决于哪一个是最合适的
当使用相同的函数来解析输入文件时,第一个函数特别有用,并且/或者我们允许每个参数/行有任意数量的双精度。它很容易在循环中使用
第二个是我在程序中最常用的。我经常使用
typedef struct {
double x;
double y;
double z;
} vec3d;
int parse_vector(const char *src, vec3d *to)
{
vec3d temp;
char dummy;
if (!src || !*src)
return -1; /* NULL or empty string */
if (sscanf(src, " %lf %lf %lf %c", &temp.x, &temp.y, &temp.z, &dummy) == 3 ||
sscanf(src, " %lf %*[.,:/] %lf %*[.,:/] %lf %c", &temp.x, &temp.y, &temp.z, &dummy) == 3) {
if (to)
*to = temp;
return 0;
}
return -1;
}
它允许在命令行上使用1+2+3、1/2/3、1:2:3甚至“1 2 3”或1 2 3指定3D向量。需要引号来阻止shell将其拆分为三个单独的参数。它不会检查双重溢出,因此在输出中显示已解析的向量非常重要,这样用户就可以检测到他们的输入是否有误
%*[,:/]中的星号*表示转换结果不存储在任何位置,并且转换不计入返回值。[是转换说明符,转换列表中的任何和所有字符,以]字符结尾。[^是相反的,转换列表中不包含的任何字符。我意识到的一件事是,在堆栈中过滤致命错误通常是不值得的。如果某个错误导致无法向前推进,只需在那里结束程序。我通常通过创建一个可以执行的错误退出函数来处理它从任何地方拨打:
void error_exit(int code, const char* message) {
printf("Error %d: %s\nExiting!\n", code, message);
cleanup();
exit(code);
}
float* nested_function(int input, ...) {
if (causes_hopeless_failure(input)) {
error_exit(err_HOPELESS, "invalid input to nested_function");
}
//normal processing proceeds ...
return valid_pointer;
}
int main() {
float* vector = function_which_eventually_calls_nested_function();
cleanup();
return 0;
}
cleanup函数用于处理程序退出时未正确清理的资源。文件句柄和分配的缓冲区通常不属于这一类。我通常将其用于需要撤消的系统配置更改。我意识到,通常不值得费心过滤堆栈上的错误。如果某个错误导致无法向前推进,只需在那里结束程序。我通常通过创建一个可以从任何地方调用的error_exit函数来处理它:
void error_exit(int code, const char* message) {
printf("Error %d: %s\nExiting!\n", code, message);
cleanup();
exit(code);
}
float* nested_function(int input, ...) {
if (causes_hopeless_failure(input)) {
error_exit(err_HOPELESS, "invalid input to nested_function");
}
//normal processing proceeds ...
return valid_pointer;
}
int main() {
float* vector = function_which_eventually_calls_nested_function();
cleanup();
return 0;
}
清理功能用于处理在程序退出时未正确清理的资源。文件句柄和分配的缓冲区通常不属于这一类。我通常将其用于需要撤消的系统配置更改。C有带外错误代码处理,它从永远都在其中
#include <errno.h>
int do_something(char* data) {
if ( data == 0 ) {
errno = ENODATA;
return 0;
}
... do stuff ...
}
如果希望链错误
int value = do_something( "one" );
if ( int errornum = errno ) {
fprintf("error (%d) could not do something: %s", strerror( errornum ) );
errno = errornum;
return; // or exit;
}
请记住,几乎每一个标准函数调用都会重置errno,因此您需要捕获它,然后在执行任何您想要的操作后可以选择再次设置它
errno的使用通常没有达到应有的程度,这可能是因为太多人首先通过特殊的哨兵/值来学习带内错误报告。此外,正确检查错误代码需要更多的代码行。也就是说,这是一个更好的解决方案,因为您不会让返回值过载数据和co同一变量中的控件信息
已经设置了许多错误代码,奇怪的是,您可以根据需要重用一个,或者选择一个足够接近的错误代码
1 EPERM Operation not permitted
2 ENOENT No such file or directory
3 ESRCH No such process
4 EINTR Interrupted system call
5 EIO I/O error
6 ENXIO No such device or address
7 E2BIG Argument list too long
8 ENOEXEC Exec format error
9 EBADF Bad file number
10 ECHILD No child processes
11 EAGAIN Try again
12 ENOMEM Out of memory
13 EACCES Permission denied
14 EFAULT Bad address
15 ENOTBLK Block device required
16 EBUSY Device or resource busy
17 EEXIST File exists
18 EXDEV Cross-device link
19 ENODEV No such device
20 ENOTDIR Not a directory
21 EISDIR Is a directory
22 EINVAL Invalid argument
23 ENFILE File table overflow
24 EMFILE Too many open files
25 ENOTTY Not a typewriter
26 ETXTBSY Text file busy
27 EFBIG File too large
28 ENOSPC No space left on device
29 ESPIPE Illegal seek
30 EROFS Read-only file system
31 EMLINK Too many links
32 EPIPE Broken pipe
33 EDOM Math argument out of domain of func
34 ERANGE Math result not representable
35 EDEADLK Resource deadlock would occur
36 ENAMETOOLONG File name too long
37 ENOLCK No record locks available
38 ENOSYS Function not implemented
39 ENOTEMPTY Directory not empty
40 ELOOP Too many symbolic links encountered
42 ENOMSG No message of desired type
43 EIDRM Identifier removed
44 ECHRNG Channel number out of range
45 EL2NSYNC Level 2 not synchronized
46 EL3HLT Level 3 halted
47 EL3RST Level 3 reset
48 ELNRNG Link number out of range
49 EUNATCH Protocol driver not attached
50 ENOCSI No CSI structure available
51 EL2HLT Level 2 halted
52 EBADE Invalid exchange
53 EBADR Invalid request descriptor
54 EXFULL Exchange full
55 ENOANO No anode
56 EBADRQC Invalid request code
57 EBADSLT Invalid slot
59 EBFONT Bad font file format
60 ENOSTR Device not a stream
61 ENODATA No data available
62 ETIME Timer expired
63 ENOSR Out of streams resources
64 ENONET Machine is not on the network
65 ENOPKG Package not installed
66 EREMOTE Object is remote
67 ENOLINK Link has been severed
68 EADV Advertise error
69 ESRMNT Srmount error
70 ECOMM Communication error on send
71 EPROTO Protocol error
72 EMULTIHOP Multihop attempted
73 EDOTDOT RFS specific error
74 EBADMSG Not a data message
75 EOVERFLOW Value too large for defined data type
76 ENOTUNIQ Name not unique on network
77 EBADFD File descriptor in bad state
78 EREMCHG Remote address changed
79 ELIBACC Can not access a needed shared library
80 ELIBBAD Accessing a corrupted shared library
81 ELIBSCN .lib section in a.out corrupted
82 ELIBMAX Attempting to link in too many shared libraries
83 ELIBEXEC Cannot exec a shared library directly
84 EILSEQ Illegal byte sequence
85 ERESTART Interrupted system call should be restarted
86 ESTRPIPE Streams pipe error
87 EUSERS Too many users
88 ENOTSOCK Socket operation on non-socket
89 EDESTADDRREQ Destination address required
90 EMSGSIZE Message too long
91 EPROTOTYPE Protocol wrong type for socket
92 ENOPROTOOPT Protocol not available
93 EPROTONOSUPPORT Protocol not supported
94 ESOCKTNOSUPPORT Socket type not supported
95 EOPNOTSUPP Operation not supported on transport endpoint
96 EPFNOSUPPORT Protocol family not supported
97 EAFNOSUPPORT Address family not supported by protocol
98 EADDRINUSE Address already in use
99 EADDRNOTAVAIL Cannot assign requested address
100 ENETDOWN Network is down
101 ENETUNREACH Network is unreachable
102 ENETRESET Network dropped connection because of reset
103 ECONNABORTED Software caused connection abort
104 ECONNRESET Connection reset by peer
105 ENOBUFS No buffer space available
106 EISCONN Transport endpoint is already connected
107 ENOTCONN Transport endpoint is not connected
108 ESHUTDOWN Cannot send after transport endpoint shutdown
109 ETOOMANYREFS Too many references: cannot splice
110 ETIMEDOUT Connection timed out
111 ECONNREFUSED Connection refused
112 EHOSTDOWN Host is down
113 EHOSTUNREACH No route to host
114 EALREADY Operation already in progress
115 EINPROGRESS Operation now in progress
116 ESTALE Stale NFS file handle
117 EUCLEAN Structure needs cleaning
118 ENOTNAM Not a XENIX named type file
119 ENAVAIL No XENIX semaphores available
120 EISNAM Is a named type file
121 EREMOTEIO Remote I/O error
122 EDQUOT Quota exceeded
123 ENOMEDIUM No medium found
124 EMEDIUMTYPE Wrong medium type
125 ECANCELED Operation Canceled
126 ENOKEY Required key not available
127 EKEYEXPIRED Key has expired
128 EKEYREVOKED Key has been revoked
129 EKEYREJECTED Key was rejected by service
130 EOWNERDEAD Owner died
131 ENOTRECOVERABLE State not recoverable
C有带外错误代码处理,从永远都在那里
#include <errno.h>
int do_something(char* data) {
if ( data == 0 ) {
errno = ENODATA;
return 0;
}
... do stuff ...
}
如果希望链错误
int value = do_something( "one" );
if ( int errornum = errno ) {
fprintf("error (%d) could not do something: %s", strerror( errornum ) );
errno = errornum;
return; // or exit;
}
请记住,几乎每一个标准函数调用都会重置errno,因此您需要捕获它,然后在执行任何您想要的操作后可以选择再次设置它
errno的使用通常没有达到应有的程度,这可能是因为太多人首先通过特殊的哨兵/值来学习带内错误报告。此外,正确检查错误代码需要更多的代码行。也就是说,这是一个更好的解决方案,因为您不会让返回值过载数据和co同一变量中的控件信息
已经设置了许多错误代码
奇怪的是,你可以根据自己的需要重复使用一个,或者选择一个足够近的
1 EPERM Operation not permitted
2 ENOENT No such file or directory
3 ESRCH No such process
4 EINTR Interrupted system call
5 EIO I/O error
6 ENXIO No such device or address
7 E2BIG Argument list too long
8 ENOEXEC Exec format error
9 EBADF Bad file number
10 ECHILD No child processes
11 EAGAIN Try again
12 ENOMEM Out of memory
13 EACCES Permission denied
14 EFAULT Bad address
15 ENOTBLK Block device required
16 EBUSY Device or resource busy
17 EEXIST File exists
18 EXDEV Cross-device link
19 ENODEV No such device
20 ENOTDIR Not a directory
21 EISDIR Is a directory
22 EINVAL Invalid argument
23 ENFILE File table overflow
24 EMFILE Too many open files
25 ENOTTY Not a typewriter
26 ETXTBSY Text file busy
27 EFBIG File too large
28 ENOSPC No space left on device
29 ESPIPE Illegal seek
30 EROFS Read-only file system
31 EMLINK Too many links
32 EPIPE Broken pipe
33 EDOM Math argument out of domain of func
34 ERANGE Math result not representable
35 EDEADLK Resource deadlock would occur
36 ENAMETOOLONG File name too long
37 ENOLCK No record locks available
38 ENOSYS Function not implemented
39 ENOTEMPTY Directory not empty
40 ELOOP Too many symbolic links encountered
42 ENOMSG No message of desired type
43 EIDRM Identifier removed
44 ECHRNG Channel number out of range
45 EL2NSYNC Level 2 not synchronized
46 EL3HLT Level 3 halted
47 EL3RST Level 3 reset
48 ELNRNG Link number out of range
49 EUNATCH Protocol driver not attached
50 ENOCSI No CSI structure available
51 EL2HLT Level 2 halted
52 EBADE Invalid exchange
53 EBADR Invalid request descriptor
54 EXFULL Exchange full
55 ENOANO No anode
56 EBADRQC Invalid request code
57 EBADSLT Invalid slot
59 EBFONT Bad font file format
60 ENOSTR Device not a stream
61 ENODATA No data available
62 ETIME Timer expired
63 ENOSR Out of streams resources
64 ENONET Machine is not on the network
65 ENOPKG Package not installed
66 EREMOTE Object is remote
67 ENOLINK Link has been severed
68 EADV Advertise error
69 ESRMNT Srmount error
70 ECOMM Communication error on send
71 EPROTO Protocol error
72 EMULTIHOP Multihop attempted
73 EDOTDOT RFS specific error
74 EBADMSG Not a data message
75 EOVERFLOW Value too large for defined data type
76 ENOTUNIQ Name not unique on network
77 EBADFD File descriptor in bad state
78 EREMCHG Remote address changed
79 ELIBACC Can not access a needed shared library
80 ELIBBAD Accessing a corrupted shared library
81 ELIBSCN .lib section in a.out corrupted
82 ELIBMAX Attempting to link in too many shared libraries
83 ELIBEXEC Cannot exec a shared library directly
84 EILSEQ Illegal byte sequence
85 ERESTART Interrupted system call should be restarted
86 ESTRPIPE Streams pipe error
87 EUSERS Too many users
88 ENOTSOCK Socket operation on non-socket
89 EDESTADDRREQ Destination address required
90 EMSGSIZE Message too long
91 EPROTOTYPE Protocol wrong type for socket
92 ENOPROTOOPT Protocol not available
93 EPROTONOSUPPORT Protocol not supported
94 ESOCKTNOSUPPORT Socket type not supported
95 EOPNOTSUPP Operation not supported on transport endpoint
96 EPFNOSUPPORT Protocol family not supported
97 EAFNOSUPPORT Address family not supported by protocol
98 EADDRINUSE Address already in use
99 EADDRNOTAVAIL Cannot assign requested address
100 ENETDOWN Network is down
101 ENETUNREACH Network is unreachable
102 ENETRESET Network dropped connection because of reset
103 ECONNABORTED Software caused connection abort
104 ECONNRESET Connection reset by peer
105 ENOBUFS No buffer space available
106 EISCONN Transport endpoint is already connected
107 ENOTCONN Transport endpoint is not connected
108 ESHUTDOWN Cannot send after transport endpoint shutdown
109 ETOOMANYREFS Too many references: cannot splice
110 ETIMEDOUT Connection timed out
111 ECONNREFUSED Connection refused
112 EHOSTDOWN Host is down
113 EHOSTUNREACH No route to host
114 EALREADY Operation already in progress
115 EINPROGRESS Operation now in progress
116 ESTALE Stale NFS file handle
117 EUCLEAN Structure needs cleaning
118 ENOTNAM Not a XENIX named type file
119 ENAVAIL No XENIX semaphores available
120 EISNAM Is a named type file
121 EREMOTEIO Remote I/O error
122 EDQUOT Quota exceeded
123 ENOMEDIUM No medium found
124 EMEDIUMTYPE Wrong medium type
125 ECANCELED Operation Canceled
126 ENOKEY Required key not available
127 EKEYEXPIRED Key has expired
128 EKEYREVOKED Key has been revoked
129 EKEYREJECTED Key was rejected by service
130 EOWNERDEAD Owner died
131 ENOTRECOVERABLE State not recoverable
请添加实际代码,以便我们有一个清晰的示例,如果*pointer=='something'很像没有做您期望的事情;您可能需要ifpointer&&strcppointer,something==0太多了,如果可能的话,我只是想知道如何返回错误。函数必须作为字符指针返回。您知道退出,对吗?如果发生不可恢复的错误,例如,当前数据集的动态内存分配失败,只需打印一条错误消息,然后立即退出程序,这是完全可以接受的。@NominalAnimal我是,但我尽量不使用它。请添加实际的代码,让我们有一个明确的例子,如果*pointer=='something'很像没有做你期望的事情;您可能需要ifpointer&&strcppointer,something==0太多了,如果可能的话,我只是想知道如何返回错误。函数必须作为字符指针返回。您知道退出,对吗?如果发生不可恢复的错误,例如,当前数据集的动态内存分配失败,只打印一条错误消息,然后立即退出程序是完全可以接受的。@NominalAnimal我是,但我尝试不使用它。请注意,上面的列表并不详尽。请注意,上面的列表并不详尽。