C 返回带有无符号值的错误?

C 返回带有无符号值的错误?,c,function,error-handling,C,Function,Error Handling,我正在制作一个数据结构库。我允许用户调用的一个功能是: 无符号整数索引(struct myDataStructure,void*value) 它搜索我的数据结构并返回该值所在的索引位置 前 {'A',D',C'} char val1 = 'A'; unsigned int location = index(s, &val1); // location = 0 char val2 = 'C'; location = index(s, &val2); // location = 2

我正在制作一个数据结构库。我允许用户调用的一个功能是:

无符号整数索引(struct myDataStructure,void*value)

它搜索我的数据结构并返回该值所在的
索引
位置

{'A',D',C'}

char val1 = 'A';
unsigned int location = index(s, &val1); // location = 0
char val2 = 'C';
location = index(s, &val2); // location = 2
如果列表中不存在该元素,那么我不知道返回什么。以下是我迄今为止排除的选项:

  • 使用
    断言
    或系统退出或异常结束运行时。我认为这没有多大用处,因为在调用
    index()

  • 返回UINT_MAX或0范围内的任何常数,您可以将指针传递到相应设置为
    true
    false
    bool

    unsigned int index(struct myDataStructure, void *value, bool *ok);
    

    您是对的,返回指向static的指针在很多方面都是不好的。它不是线程安全的,更糟糕的是,它邀请用户做类似的事情

    int *aIndexLoc = index(data, &a);
    int *bIndexLoc = index(data, &b);
    if (aIndexLoc && bIndexLoc) 
      printf ("a's loc is %u; b's loc is %u\n", *aIndexLoc, *bIndexLoc);
    
    当然,答案是错误的

    首先。。。如果您希望您的库能够经得起未来的考验,那么不要为数组索引返回unsigned。返回
    size\u t

    然后。。。有几种处理错误返回的习惯用法。最常见的方法是返回
    int
    或enum错误代码作为函数值,并使用指针arg返回实际返回值。按照惯例,
    0
    表示“正常”,非零值是各种错误代码。此外,如果您的数据结构超过几个字节,请不要传递它的完整副本。传递指针

    typedef int ERROR;
    ERROR index(size_t *result, struct myDataStructure *myStruct, void *valueToFind);
    
    从那里可以看出:

    size_t loc[1];
    struct myDataStructure someData[1];
    int aValue[1];
    
    initialize(someData);
    get(aValue);
    
    ERROR error = index(loc, someData, aValue);
    if (error) {
      fprintf(stderr, "Couldn't find the value. Error code: %d\n", error);
      return;
    }
    
    单元素数组是一种技巧,它允许您以相同的方式编码对象是在堆栈还是堆上分配的。可以将数组的名称视为指针。例如,
    someData->fieldName
    *loc
    工作正常。

    几种可能性:

    • 错误返回时
      (unsigned int)-1
      使用

      unsigned int index(struct myDataStructure, void* value)
      
      ssize_t index(struct myDataStructure, void* value)
      
    • 错误返回时
      -1
      使用

      unsigned int index(struct myDataStructure, void* value)
      
      ssize_t index(struct myDataStructure, void* value)
      
      ssize\u t
      is POSIX)

    • 传入一个
      无符号int
      的地址以指向结果,并在出错时返回
      -1
      ,成功时返回
      0
      ,使用

      int index(struct myDataStructure, void* value, unsigned int * result)
      
    使用

    • 我觉得这里的断言不合适,因为它结束了您的程序
    • 静态缓冲区是上个千年的编码风格。它使库在多线程上下文中不可用

    您可以传递指向存储错误值的变量的指针:
    无符号整数索引(struct myDataStructure,void*value,int*status)。您也可以考虑使用POSIX <代码> SsiZeZt<<代码>类型,而不是<代码>无符号< /代码>。code>ssize\u t
    的宽度与
    size\u t
    的宽度相同,但保证能够保持
    -1
    的值。但有一个批评是,我确实希望避免污染全局命名空间。使用特殊的错误代码会使新用户对API产生混淆。@好吧,您的示例只允许两种情况:非null和null。通过扩展,ERROR有两个值:0和一些非零值,比如1。typedef只是为返回的内容命名的一种方式。它是一个布尔值,表示是否存在错误。除非您选择这样做,否则这不会污染名称空间。我看不出用户在这一点上感到非常困惑。事实上,任何做过重要的C编程的人都会发现它非常熟悉。不幸的是,第一个选项可能会导致我的库中不小心的用户越界。第二个选项使用我不喜欢的外部库。这会影响便携性。第三个可能是最好的选择,但我无法决定是将
    unsigned int
    作为返回值还是参数。我想可能是安全参数?将返回类型设置为
    bool
    以便不执行
    myArr[index(myArr,“F”)]
    @hatefind:“可能会导致我的库中不小心的用户越界”和“以便不执行”在任何情况下,您都应该期望您的用户阅读文档并对每个可能失败的函数调用应用正确的错误检查。我的意思是,我希望API调用能够非常简单地使用。如果
    index()
    可能失败,则可能不会像这样
    myArr[index(myArr,“F”)]
    。这是没有办法的。