4

曾经有人要求我编写一个函数,该函数将在某些成功条件下返回指向内存中某些数据的指针,否则它应该返回“-1”。在这种情况下,正确的返回类型是什么。如果我只需要返回数据,那么我会将 char * 作为函数 myfunction 的返回类型。但在这种情况下,我可能会返回 -1 具有返回类型。

<what-type> myfunction() {

char *data;

if (some condition true)
  return data;
else 
  return -1
}

int main () {

 myfunction

}
4

5 回答 5

7

使用union并可能为它定义一个typedef

IE

typedef struct {
   int is_error;
   union {
     int error_code;
     char *data;
   }
} ReturnType;

然后

ReturnType myFunction(....) { ... etc }

调用者可以检查函数是否错误(获取返回错误代码)或获取data其他错误。

于 2013-05-23T03:33:10.527 回答
4

如果要返回不同的数据类型,请使用void*

void* myfunction();
^^^^^

在您的情况下,返回 aNULL似乎是更理想的解决方案,而不是-1.
它将允许您的函数的用户编写代码,例如:

if(myfunction())
{
    //Utilize the returned string
}
于 2013-05-23T03:20:37.893 回答
0

将返回指针的函数..在某些成功条件下,它应该返回“-1”。

帮自己一个忙,不要错误指示和函数结果混入这样的一个对象中。通过让函数只返回一个布尔成功指示符,将它们分成两个不同的实体,并通过一个指针返回实际结果数据,如

bool myfunction(char **result_ptr) {
        char *data;

        if (some error condition)
                return false;

        *result_ptr = data;
        return true;
}

int main () {
        bool success;
        char *data:

        success = myfunction(&data);
        if (success)
                use(data);

}

带内错误指示器使糟糕的 API 经常导致失败(在realloc函数的极端情况下,它请求你编写代码,以防万一失败时丢失原始指针),并且它至少会导致以下优秀 API 的特征

  • 易于使用,即使没有文档
  • 难以滥用
  • 易于阅读和维护使用它的代码

CERT从安全角度建议反对他们。

于 2016-06-26T15:01:16.467 回答
-1

如果不使用 NULL,那么您可以对返回值进行类型转换

char* myfuntion(){  
                return (char*)-1;
}
int main () {
 printf("%d",myfuntion());
}
于 2013-05-23T07:29:05.127 回答
-1

可以将 -1 转换为 void * 并检查它。你可以返回 ((void *)-1); 请注意,C 中没有指针符号的概念。

如果您认为这感觉有点疯狂:-) 您可能是对的。但是在某些情况下,这种约定可能对错误处理很有用。在重要的项目中也有它的用途。特别是 pthread 库的特定实现有时会使用此约定。

指针(地址)可以是负数吗?

有很多话要说。

关于按值对指针进行特殊解释的概念。

好的,所以似乎存在一些关于如何保证 (void*)-1 不是实际指针的问题。并且@ictoofay 似乎认为我以某种方式提到了关于 (void *)-1 上面的保证以及它如何不能是有效地址,我想澄清一下我没有。

话虽如此,假设一个系统使用直接内存映射而不是虚拟地址。(void *)-1 将是该模型中的最后一个地址,从最严格的意义上讲,您不应该使用它。但是,您可以对最后一个物理地址的存储容量进行假设(参见下面的 ldl 示例)

但是通过检查现实生活项目中的价值来“特殊”解释指针的概念并不新鲜。实际上,这是大多数现代操作系统在进行内存地址管理时使用的概念。系统将使用地址和地址范围并将它们用于“特殊含义”是很常见的。所以实际上,作为一名程序员,你实际上可以自由地做出任何假设并接受它们的后果。(void *)-1 可以用作特殊值的概念并不牵强。请注意,这仍然没有说明该概念与 (void *)-1 在给定情况下可能是有效地址这一事实的 (in?) 兼容性。

现在解决这个“疯狂”的概念以及为什么有人会使用。以下是 (void*)-1 安全的两个现实生活示例。

pthreads 在 Linux、HPUX、solaris 和大多数 BSD 上使用它。

特别是 PTHREAD_CANCELED 是 ((void *)-1)

从 pthread.h

#define PTHREAD_CANCELED ((void *) -1)

它在 pthread 库的 darwin 版本中定义为 ((void *)1)。好玩;

在 glibc(定义了 _GNU_SOURCE)中,ld.so 提供了在动态加载的库中搜索相同符号的替代值的能力。RTLD_NEXT 的值为 (void *)-1。

关于C的流动性的思考

在 C 中,没有理由必须以特定方式解释给定值。C 没有严格的类型,并且在这些概念中是流动的。它的很多力量都来自于此。

关于 NULL 的“值”

一个符合标准的 C 实现#define NULL 可以是古怪的吗

对概念有有趣的解释。

于 2013-05-23T03:48:39.010 回答