【问题标题】:void** parameter called with a fixed array value使用固定数组值调用的 void** 参数
【发布时间】:2011-11-30 21:46:38
【问题描述】:

我声明了一个固定大小的数组:

int vals[25];

我想将数组发送到一个函数,该函数将分配 vals 的值:

bool FetchValueArray(char* source, char* name, char* typeFormat, int count, void** destination)
{
    int i;
    char *t;
    t=strstr(source,name);
    if (t)
        if (destination != NULL)
        {
            for (i = 0;i < count;i++)
                sscanf(t,typeFormat,destination[i]);
                return true;
        }
    return false;
}

这基本上会在某个搜索字符串之后读取所有内容。例如:

FetchValueArray(source,"CONFIG=","%d",15,vals);

其中“CONFIG=”是纯文本,后跟 15 个制表符分隔的数值。

这里有一些关于间接和固定 aized 数组的事情我离 grokking 还很远,因此我想知道是否可以将固定大小的数组作为 void** 的参数发送(即使相信数组的大小会得到尊重。不同的问题。)


tl;dr 版本

int vals[25];
bool foo(int size,void** d);
foo(25,vals);

为什么不允许这样做?

【问题讨论】:

  • 数组在传递给函数时衰减为指针。是的,您可以将其命名为void*。我不知道你为什么要改用void**

标签: c void-pointers indirection multiple-indirection


【解决方案1】:

数组衰减为指向其第一个元素的指针,指向任何类型的指针都可以隐式转换为void*。其次,为了使数组访问正常工作,FetchValueArray 需要知道每个数组元素有多大。您正在尝试传递一个void**,它是一个指向void* 的指针,因此数组访问将每个元素视为它具有void* 的大小,这是错误的——您的数组元素有大小int,不一定和void*的大小一样。

所以void** 是错误的。相反,您需要传入void*,这意味着“指向未知类型的指针”。您不能在void* 上使用数组索引,因为编译器不知道底层指向类型的大小。你需要帮助它。例如:

bool FetchValueArray(char* source, char* name, char* typeFormat, int count, void* destination, size_t destElementSize)
{
    ...
    sscanf(t, typeFormat, (char*)destination + destElementSize * i);
    ...
}
...
FetchValueArray(source, "CONFIG=", "%d", 15, vals, sizeof(vals[0]));

在这里,我们手动执行数组索引——我们将void* 转换为char*,它具有已知的指向大小(1 字节),然后通过乘以执行数组偏移量每个元素的大小。结果是指向正确内存位置的指针,这是sscanf 所期望的。

不过,在这里要非常小心——我认为你应该重新考虑你的设计。编译器不知道您的函数的语义,因此它无法验证您是否传递了正确的参数。在这里很容易插入一个意外的安全漏洞而没有意识到。考虑一下编译器可以更彻底地验证的不同设计是否会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多