确定具有正确返回类型的原型的存在

时间:2010-12-19 16:03:14

标签: c prototype

这是我提出的C黑魔法中的一个随机问题:

编写一个函数,如果malloc已经原型化,则返回1以返回指针类型;如果malloc的返回类型为int,则返回0(隐式或由于错误的原型) ,,不调用任何实现定义或未定义的行为

我相信它是可以解决的,但我还没有找到解决方案。请注意,调用函数不是必需的,实际上是不可能的,因为调用具有不正确原型的函数是未定义的行为。我对成分有一些想法,但我认为如果我暂时把它们排除在外,它会带来更好的谜题(也可能是更多样化的想法)。

我不需要立即使用该解决方案,但它在configure脚本等方面可能很方便。

更新:有用性的更好示例(使用strdup代替malloc):

#undef strdup
#define strdup(x) (strdup_has_proto ? strdup((x)) : my_strdup((x)))

即。能够在源级别实现X_has_proto作为表达式可以是一种可移植的方式来使用系统可能具有或不具有的功能,并且可以回退到本地替换,而无需任何单独的configure步骤

4 个答案:

答案 0 :(得分:0)

假设没有解决方案。你需要的是一个函数,它的主体有自由变量,代表编译器中的中间类型信息,除了实现定义的方式之外,它们不会降低到目标语言中,例如:调试器信息。放宽要求,以便允许某些规定类型的实现定义的行为,您可能会找到解决方案。

答案 1 :(得分:0)

部分答案和相关问题的答案:

如果有问题的函数应该返回浮点类型,那么测试很简单:

#define HAS_PROTO_FP_RET_1_ARG(f) !!((1?1:(f)(0))/2)

当且仅当声明f返回浮点类型时,1才会被提升为浮点类型,当且仅当1具有浮点类型时,除以2会产生非零值。 / p>

此测试可用于检查C99数学函数的存在。

使用指针,表达式(1?0:(f)(0))可能很有用 - 它根据返回值计算为0int)或(void *)0)(空指针常量)类型f。但我还没有找到任何狡猾的方法来测试表达式是否具有整数或指针类型。

我遇到的一个大问题是void *不能参与指针运算,也不会在算术上下文中隐式转换为其他指针类型。例如,如果确实如此,这将起作用(稍微违反我关于UB / IDB的规则):

#define HAS_PROTO_PTR_RET_1_ARG(f) ((int)((char (*)[2])2 - (1?0:(f)(0))) == 1)

解决这个问题的任何想法?

更新:我的解决方案仅取决于intmax_t大于int

#define HAS_PROTO_PTR_RET_1_ARG(f) ( \
    sizeof(int)!=sizeof(void *) ? sizeof ((f)(0)) == sizeof(void *) : \
    sizeof (1?(intmax_t)0:(f)(0)) == sizeof(void *) )

有两种情况。如果intvoid *的大小不同,我们只需检查返回值的大小。否则,intvoid *的大小相同,因此(根据大的假设)intmax_tvoid *的大小不同。如果返回类型为intmax_t,我们构造一个类型为int的表达式,如果返回类型为void *,则构造为void *,并测试其大小。

此宏仅在intintmax_tvoid *都具有相同大小的计算机上失败。实际上,这意味着仅适用于64位或更大int的DSP。由于几乎所有真正的POSIX和类似POSIX的系统都具有固定大小的32位int,并且intmax_t需要至少为64位,因此这足以让我满意。

答案 2 :(得分:0)

由于可以添加void *int,我正在考虑尝试其他运算符,例如比较。结果,尤其是R的?:技巧,结果奇怪地不一致:

int f() { return 0; }

void *g() { return 0; }

#define T(x)  (1?0:x())   /* R's trick from a comment */

void h()
{
    void *n = 0;
    int i = 0;

    f() > n;  /* m.c:12: warning: comparison between pointer and integer */
    g() > n;
    T(f) > n;
    T(g) > n;

    f() > i;
    g() > i;  /* m.c:18: warning: comparison between pointer and integer */
    T(f) > i;
    T(g) > i; /* m.c:20: warning: comparison between pointer and integer */
}

答案 3 :(得分:-2)

一些光荣糟糕的黑客怎么样?

char has_malloc = 0;
#define malloc(x) \
     has_malloc = 1; \
     malloc((x))
//.. run includes here
#undef malloc

但是,你可以#include <malloc.h>获得保证。

编辑: 为什么不直接定义一个int malloc()?如果有人试图调用int malloc,它应该调用你的版本。