获取作为void *传递的struct数组中的指针

时间:2015-09-21 06:51:45

标签: c pointers casting

我有一个带有qsort的签名的函数:

const char* get_str(int i, const void *base, size_t nmemb, size_t size);

我传递了指向const char*的指针数组,或者第一个字段是const char*指针的结构数组。

我需要做什么演员才能在数组元素i中提取指针?

我已经尝试将base转换为char本身的数组,因此我可以进入正确的元素:

return *(const char**)(((const char*)base)[i * size]);

但编译器抱怨:警告:从不同大小的整数转换为指针[-Wint-to-pointer-cast]

2 个答案:

答案 0 :(得分:1)

看起来你想为结构体实现类型或识别系统,如下所示:

#include <stdlib.h>
#include <stdio.h>

struct a {
    const char *id;
    int x;
};

struct b {
    const char *id;
    double d;
};

union any {
    struct a a;
    struct b b;
};

int main()
{
    struct a a[] = {{"one", 1}, {"two", 2}, {"three", 3}};
    struct b b[] = {{"pi", 3.1415}, {"e", 2.71}};
    union any any[3];

    any[0].a = a[0];
    any[1].b = b[0];
    any[2].a = a[1];

    puts(get_str(1, a, 3, sizeof(*a)));
    puts(get_str(1, b, 2, sizeof(*b)));
    puts(get_str(1, any, 3, sizeof(*any)));

    return 0;
}

在这种情况下,以下工作:

const char* get_str(int i, const void *base, size_t nmemb, size_t size)
{
    const char *p = base;
    const char **pp = (const char**) (p + i * size);

    return *pp;
}

这可以写成一行:

const char* get_str(int i, const void *base, size_t nmemb, size_t size)
{
    return *(const char**) ((const char *) base + i * size);
}

但我认为通过无效指针绕行是没有必要的。您可以使用类型化数组进行地址计算:

puts(*(const char **) (&a[1]));
puts(*(const char **) (&b[1]));
puts(*(const char **) (&any[1]));

如果你把它包装在一个函数中:

const char *get_str(const void *str)
{
    return *(const char **) str;
}

你得到:

puts(get_str(&a[1]));
puts(get_str(&b[1]));
puts(get_str(any + 1));
在我看来,

qsort ish语法更具可读性。

这样可行,因为您只能访问已知位置的一个元素。但是,函数bsortqsort不能使用这种技术,因为它们必须在多个索引处访问数组,因此必须能够自己进行索引计算。

答案 1 :(得分:0)

找到我(好吧,“又一个”,但假设这个括号从未存在过!)该编译器中的一个错误,我给你一个免费的 cookie!

编译器是对的。此

*(const char**)(((const char*)base)[i * size]);

将类型编译为类似(语法:expresion -> type)...

base -> const void*
(const char*)base -> (const char*)const void*
(((const char*)base)[i * size]) -> *(const char*)const void* -> const char // Here's the problem!
(const char**)(((const char*)base)[i * size]) -> (const char**)const char // Now, this is *not* good...
*(const char**)(((const char*)base)[i * size]) -> *(const char**)const char -> const char* // Well, we have now just perfectly dereferenced '~'...

不是很理智,不是吗?*

BTW :您没有向我们提供足够的信息来为您的问题提供完整的解决方案。你谈到的那些struct是什么?

编辑:这可以帮助您(根据评论撰写)吗?

*(const char**)&(((const unsigned char*)base)[size * i])