使用固定数组值调用 void** 参数
我声明了一个固定大小的数组:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
数组会衰减为指向其第一个元素的指针,并且指向任何类型的指针都可以隐式转换为
void*
。其次,为了使数组访问正常工作,FetchValueArray
需要知道每个数组元素有多大。您尝试传递一个void**
,它是一个指向void*
的指针,因此数组访问将每个元素视为具有大小code>void*
,这是错误的——数组元素的大小为int
,它不一定与void*
的大小相同。所以
void**
是错误的。相反,您需要传入void*
,这意味着“指向未知类型的指针”。您不能在void*
上使用数组索引,因为编译器不知道底层指向类型的大小。你需要帮助它。例如:在这里,我们手动执行数组索引 - 我们将
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 avoid**
, which is a pointer to avoid*
, so the array access treats each element as if it had the size of avoid*
, which is wrong -- your array elements have sizeint
, which is not necessarily the same as the size of avoid*
.So
void**
is wrong. You instead need to pass invoid*
, which means "pointer to unknown type". You can't use array indexing on avoid*
, since the compiler doesn't know the size of the underlying pointed-to type. You need to help it out. For example:Here, we're performing the array indexing manually -- we're casting the
void*
tochar*
, 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 whatsscanf
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.