我试图编写一个通用函数来打印数组的元素。这就是我所拥有的:
void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){
void *dest[numElements];
memcpy(dest, &source, (size * nElem));
int i;
for (i = 0; i < numElements; i++){
printFunction(dest[i]);
}
}
我传递了一个数组的地址,数组中元素的数量,数组中每个元素的大小,以及一个回调函数来处理它所用的任何类型的数组的打印/格式化(打印功能)工作正常,我已经测试过了。)
现在它打印出第一个元素,然后我发现了分段错误。我无法弄清问题是什么 - 任何帮助都会非常感激。我是stackoverflow的新手,所以让我知道我是否可以改进我的问题。
答案 0 :(得分:1)
你为什么要复制?
你真正想要的是传递一个char指针,这样你就可以增加它
size
从0
到numElements
次,每次都将其传递给printFunction。
请注意,您实际上编写的函数比只打印数组的函数更通用。你有效地写了一张地图&#39;将函数映射到数组的函数。
这样的事情应该有用(注意它未经测试):
void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){
int i;
for (i = 0; i < numElements; i++){
printFunction(((char *)source) + i * size);
}
}
答案 1 :(得分:1)
我假设source
是数组开头的void *
(而不是指针数组)。在那种情况下......
无需复制数组 - 您只需使用source
本身即可。并且由于允许在C中修改函数参数并且仅影响函数内的副本,因此在继续执行数组时可以更改source
和numElements
。考虑到这些要点,您可以将功能简化为以下内容:
void printArray(void *source, int numElements,
int size, void (*printFunction)(void *))
{
for (; numElements; numElements--) {
printFunction(source);
source = ((char *)source) + size;
}
}
上面的版本运行for
循环,递减numElements
以为每个数组元素提供一次传递。在每次传递结束时,source
被size
偏移,以便在将其传递给回调函数后转到下一个元素。 (char *)
强制转换用于允许指针算术,即使source
是void *
。
答案 2 :(得分:0)
您应该使用char
数组来对数据进行别名,而不是void*
数组。后者是一个指针数组,它不适合缓冲区。
泛型函数看起来应该更像这样:
void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){
char dest[numElements*size];
memcpy(dest, source, (size * numElements)); // source is already a pointer, don't address it
int i;
for (i = 0; i < numElements; i++){
printFunction(dest[i*size]); //make sure you index based on the type and not just a single byte
}
}
答案 3 :(得分:0)
它甚至更简单,不需要乘法,只需指针算术:
void printArray(void *source, int numElements, int size, void (*printFunc)(void *)){
while (numElements--) {
printFunc(source);
source=(char *)source+size; //C forbids void* math. source+=size fails on MSVC
}
}
答案 4 :(得分:-1)
void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){
int i;
for (i = 0; i < numElements; i++){
printFunction((source + i * size));
}
}
在您的程序中,您将源内容保存到void指针数组,以便在打印时获得段错误。相反,您可以直接使用source,以便获取您必须添加大小的每个元素来源。