-3

假设我有一个应该接受任意数量参数的函数,所以我在这里要做的是声明没有原型,并在代码中调用该函数时创建该函数。我正在使用指向 void 的指针来接收随机数的参数参数,但是,在这样做时,对第一个参数的内存地址的引用是唯一传递的东西,所以要让它工作,我必须声明变量的顺序与我将在代码中调用它们的顺序相同:

unsigned char result=0;
unsigned char a=1; 
unsigned char b=2;
unsigned char c=3;

char main (void)
{
    for (;;)
    {
        result = function (&a, &b, &c);
        result = function (&c, &b, &a);
    }
}

function (void *vPointer)
{
    return (1);
}

此外,我声明没有类型的函数,因为它与调用不匹配(它也被隐式声明)。

这里的结果是对函数中发送的第一个参数的引用,所以如果 i 在第一个函数调用中指向下一个地址,它将起作用,但在第二个调用中,它获取对 c 的引用,以及任何内存在它放置的位置之前。

任何人都知道以正确方式对参数进行排序的方法吗?还是在函数中接收未知数量参数的有效方法?

注意:(...)不得使用。

4

4 回答 4

2

所有C 函数都应该有原型。它们实际上不是强制性的,但没有充分的理由不使用它们(除非您被不支持它们的 pre-ANSI 编译器所困扰)。(但请参阅此答案的底部。)

如果您想要一个接受可变数量参数的函数,则该原型应以 结尾, ...,并且函数本身应使用该<stdarg.h>机制来处理其参数。(这需要至少一个具有已定义类型的参数;该参数用作以下参数的锚点。)在此处和其他地方都有记录。

在我输入此内容时,您使用“注意:不应使用任何库(例如 (...) ) ”更新了您的问题。<stdarg.h>是所有符合 C 实现(包括独立(嵌入式)实现)所需的少数头文件之一——因为它不定义任何函数,只定义类型和宏。您的 C 实现应该支持它。如果不是,那么它不是一个符合标准的 C 实现,您需要准确地告诉我们您正在使用什么编译器和/或阅读它的文档以了解它如何处理可变参数函数或等效函数。

如果您真的不能使用, ...and <stdarg.h>(或者可能是较旧的<varargs.h>),那么您可以使用固定数量的参数定义您的函数,足以满足所有用途,然后让调用者传递额外的空指针。

编辑:

这是基于评论和聊天中的新信息的更新。

OP 有一个家庭作业要printf为一些 TI 微控制器实现,由于某种原因使用, ...符号或<stdarg.h>. 有问题的编译器显然实现了 C89/C90,因此它确实支持这两个特性;这是一个任意限制。

该信息应该存在于问题中,这就是为什么在 OP 更新它之前我不赞成它的原因。

没有可移植的方法来实现这一点——这正是为什么它是, ...标准语言<stdarg.h>的一部分,也是标准库的一部分。

可能最好的方法是编写一个使用, ...and的程序<stdarg.h>,然后调用编译器,以便它只显示预处理器的输出(解析各种va_*宏和va_list类型),然后模仿它。而且您必须假设或使用编译器文档验证可变参数和非可变参数函数的调用约定是兼容的。换句话说,找出这个特定的实现做了什么,然后重新发明一个类似的轮子。

(我希望家庭作业的重点是展示标准技术有多好。)

更新 2:

我在上面写道,所有 C 函数都应该有原型。这实际上可能是该规则的一个罕见例外。至少其中一个调用:

printf("Hello\n");
printf("x = %d\n", 42);

必须从符合要求的编译器生成诊断,除非printf声明为, ...(家庭作业禁止这样做),或者没有可见的原型printf。如果没有原型,那么至少有一个调用将具有未定义的行为(C 标准未定义的行为,尽管它可能由特定的编译器定义)。

实际上,为了满足作业要求,您必须假装您使用的是 ANSI C 之前的编译器。

于 2013-03-10T18:09:52.600 回答
1

使用具有可变参数的函数的唯一“干净”方法是使用可变参数函数:

#include <stdarg.h>

void myfun(int foo, ...) {
       va_list ap;
       va_start(foo, ap);
       // ...
       va_end(ap);
}

你需要确保你知道你实际期望的参数(通常你要么使用你的第一个参数来指示期望有多少(和哪些)参数(示例是一个int说“现在来参数”),或者一个格式字符串像“%d %s:%s”,表示现在有一个 int 和两个 char*),或者你使用一个最终的终止参数(例如,读取参数直到你遇到 NULL)。

于 2013-03-10T18:13:32.563 回答
0

您可以使用结构:-

typedef struct _Params {
   int m_a;
   int m_b;
   int m_c;
} Params;

那么你的参数就不能混淆了。就像您需要的最大字母一样。

于 2013-03-10T18:29:46.597 回答
0

您可以使用可变长度的数组:

unsigned char result=0;
unsigned char a=1; 
unsigned char b=2;
unsigned char c=3;

function (int len, void *vPointer);

int main (void)
{
    for (;;)
    {
        unsigned char args[3];
        args[0] = a;
        args[1] = b;
        args[2] = c;
        result = function (3, args);
        args[0] = c;
        args[1] = b;
        args[2] = a;
        result = function (3, args);
    }
    return 0;
}

function (int len, void *vPointer)
{
    return (1);
}

但我建议您改用标准方式,即可变参数函数。

//jk

于 2013-03-10T18:23:51.580 回答