Scala的Option或Rust的Result在C中的错误处理

6

我在专业使用Scala和Python一段时间后,又开始写C语言。 在使用Scala的“Option”和“Either”错误处理模式以及最近尝试Rust后,我希望在C中实现类似的功能。因此,我想到了以下代码:

typedef struct {
    int age;
    char* name;
} User;

typedef struct {
    char* error;
    User* value;
} UserResult;

UserResult get_user() {
    /* Some complicated user fetching process .. that fails */
    return (UserResult) { .error = "403 Unauthorized\n" };
}

int main(void) {
    UserResult res = get_user();
    if (res.error)
        handle_error(res.error);
    if (res.value)
        do_something(res.value);
    /* ... */
    return 0;
}

但这并不是完全安全的(我们可能会访问无效指针)。我如何在C语言中实现类似于Scala或Rust处理错误的方式?
编辑:更正了UserResult字段名称“value”。
2个回答

6

现有的C代码中处理错误的方法有很多种。要理解如何处理各种库的错误,甚至在同一个项目中同时使用多个库,这代表了一种不可忽视的心理负担。

引入一种新的处理错误的方式可能是有益的,但另一方面,它可能类似于这个著名的XKCD漫画

Rust(以及Scala等语言)的方法确实非常强大,并且比其他旧惯用法具有一些优势。

然而,Result惯用法基于Sum Types,而C语言并不本地支持这种类型。

没有保证您的处于一致的状态。usererror都可以是null或非null。

这可以稍作修改,例如使用union:

typedef struct{
    union {
        char* error;
        User user;
    }
    bool has_error;
} UserResult;

has_error标记表示哪个字段实际上已填写:

int main(void) {
    UserResult res = get_user();
    if (res.has_error)
        handle_error(res.error);
    else
        do_something(res.value);
    /* ... */
    return 0;
}

这并不完美,因为C语言没有强制执行正确的联合访问,而是在使用不正确时会引发未定义行为


4
问题在于即使在 C 中使用了 UserResult 模型,程序员仍然需要记得进行空值检查,也就是说,编译器不会强制执行它,因此尽管我们声明了 UserResult ,但仍然有可能由于疏忽而错误地编写代码。
int main(void) {
  UserResult res = get_user();
  do_something(res.value); // Runtime error: oops I forgot to null-check and unfortunately compiler is still happy
  return 0;
}

在使用Scala的Option时,程序员被编译器强制处理情况,例如:
case class User(age: Int, name: String)
case class UserResult(value: Option[User], error: Option[String])

def get_user(): UserResult = {
  /* Some complicated user fetching process .. that fails */
  UserResult(value = None, error = Some("403 Unauthorized"))
}

def do_something(user: User) = ???

object Main extends App {
  val res = get_user()
  do_something(res.value) // Compile-time error: oops I forgot to "null-check" but fortunately the compiler is unhappy
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接