使用无符号值返回错误?

时间:2017-06-13 03:19:44

标签: c function error-handling

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

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

它搜索我的数据结构并返回该值存在于其中的index位置。

离。

{ 'A', 'D', 'C' }

char val1 = 'A';
unsigned int location = index(s, &val1); // location = 0
char val2 = 'C';
location = index(s, &val2); // location = 2

如果列表中不存在该元素,那么我不知道该返回什么。以下是我目前排除的选项:

  • 使用Assert或系统出口或例外来结束运行时。我不认为会有很多用处,因为在调用contains
  • 之前,用户必须调用index()以确保元素在结构中
  • 返回UINT_MAX或0 <= UINT_MAX范围内的任何常量。这些可能是指数值。
  • 将返回类型更改为long,以便我可以返回-1。我不想切换数据类型。
  • 让用户传入**unsigned int,以便我可以将其指向NULL(如果不存在)或实际索引值。对于阅读我的API以理解的人来说,这不是用户友好的。

我有最好的解决方案:

// Change return type to pointer.
unsigned int* index(struct myDataStructure, void* value)
{
     static int val;

     if (value exists...)
     {
          val = correct index value
          return &val;
     }
     else
     {
          return NULL;
     }
}

但我仍觉得这个解决方案很差。

3 个答案:

答案 0 :(得分:1)

你是对的,返回指向静态的指针在很多方面都很糟糕。它不是线程安全的,而且 - 更糟糕 - 它邀请用户做类似

之类的事情
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_t

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

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;
}

1元素数组是一个技巧,它允许您以相同的方式编码,无论对象是在堆栈还是堆上分配。您可以将数组的名称视为指针。例如。 someData->fieldName*loc工作正常。

答案 1 :(得分:1)

几种可能性:

  • 使用

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

    返回错误-1
    ssize_t index(struct myDataStructure, void* value)
    

    ssize_t是POSIX)

  • 传递unsigned int的地址以指向结果,并在错误时返回-1,并在成功时返回0

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

使用

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

答案 2 :(得分:0)

您可以将指针传递给相应设置为booltrue的{​​{1}}。

false