使用固定数组值调用 void** 参数

发布于 2024-12-08 02:33:43 字数 849 浏览 0 评论 0原文

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

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 个制表符分隔的数值。

这里有一些关于间接和固定大小数组的事情我还远没有理解,因此我想知道是否可以将固定大小的数组作为参数作为 void** 发送(即使存在相信数组的大小将受到尊重。)


tl;dr version

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

为什么这是不允许的?

I have a fixed-size array declared:

int vals[25];

And I'd like to send the array to a function which will assign the values of 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;
}

This will essentially read everything at after a certain search string. For example:

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

Where "CONFIG=" is in plain text, followed by 15 tab separated numeric values.

There's something here I'm far from grokking about indirection and fixed aized arrays thus I'd like to know if a fixed sized array can be sent as a parameter as void** (even if there is the leap of faith that the size of the array will be respected. Different issue.)


tl;dr version

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

Why is this not allowed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

会发光的星星闪亮亮i 2024-12-15 02:33:43

数组会衰减为指向其第一个元素的指针,并且指向任何类型的指针都可以隐式转换为 void*。其次,为了使数组访问正常工作,FetchValueArray 需要知道每个数组元素有多大。您尝试传递一个 void**,它是一个指向 void* 的指针,因此数组访问将每个元素视为具有 大小code>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 byte),然后通过乘以每个元素的大小来执行数组偏移。结果是一个指向正确内存位置的指针,这正是 sscanf 所期望的。

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

Arrays decay into pointers to their first elements, and pointers to any type can be implicitly cast to void*. Secondly, in order for array access to work properly, FetchValueArray needs to know how large each array element is. You're trying to pass a void**, which is a pointer to a void*, so the array access treats each element as if it had the size of a void*, which is wrong -- your array elements have size int, which is not necessarily the same as the size of a void*.

So void** is wrong. You instead need to pass in void*, which means "pointer to unknown type". You can't use array indexing on a void*, since the compiler doesn't know the size of the underlying pointed-to type. You need to help it out. For example:

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]));

Here, we're performing the array indexing manually -- we're casting the void* to char*, which has a known pointed-to size (1 byte), and then performing the array offset by multiplying by the per-element size. The result is a pointer to the proper memory location, which is what sscanf expects.

Be very careful here, though -- I think you should reconsider your design. The compiler doesn't know the semantics of your function, so it can't verify that you're passing the proper arguments. It's very easy to insert an accidental security vulnerability without realizing it here. Think about if you might be better off with a different design that the compiler can verify more thoroughly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文