void指针的索引

时间:2014-02-14 13:59:41

标签: c pointers indexing

因为我尝试了不同的方式来访问二进制数据的子部分,所以我正在玩这个并尝试过:

typedef struct structTest {
    unsigned char c;
    unsigned short s;
    unsigned int i;
} Test;

int main(void)
{
    char blah[10] = "hello";
    void * ptr = blah;

    char e;
    long l;

    memcpy(&e, &ptr[1], sizeof(char));
    memcpy(&l, &ptr[1], sizeof(long));
    char * s = (char *) &l;
    printf("%c %s\n",e,s);

    Test t;
    t.c = 255;
    t.s = 2705;
    t.i = 150586;

    void * v = (void *) &t;

    int i;
    short sh;

    memcpy(&sh, &v[1], sizeof(short));
    memcpy(&i, &v[3], sizeof(int));
    printf("%hd, %d\n", sh,i);
    return 0;
}

第一位打印'e'和'ello',这是它的目的。 第二位不符合预期。

我真正不清楚的是&v[n]中的数字实际上是指什么,因为我总是想象一个空指针指向的是一个没有任何内部数据的大数据师。我的初步猜测(因此假设上述情况可行)是它将其划分为字节数组。显然那是错的。同样清楚的是,编译器并没有抱怨我索引一个void指针,即使没有一个类型来定义大小它没有真正的方法来告诉索引引用的大小。所以它必须有一些理解的尺寸?除非它只是一个大小,否则第一位将不起作用,除非该大小是一个字节。

我想也许大小是由第三个参数定义的?

有人想帮帮我吗?

1 个答案:

答案 0 :(得分:2)

您正在尝试通过void指针访问结构的成员。但是,你 忘记的是,编译器可以自由地添加结构的成员字段的填充位/字节。
您无法保证结构的第二个成员始终位于同一位置。

您可以使用offsetof宏(位于stddef.h标题中)找到成员的正确偏移量。
但是,这仍然不会像您期望的那样工作,因为不允许在void指针上进行指针运算。因此,您仍然必须将其投射到您正在使用的类型 查看答案to this question了解详情。

第一位工作的原因(非标准行为,假设不允许对空指针进行指针运算)是char 保证为1字节在尺寸方面。总是。到处。完全停止 这就是为什么,如果你要在void *上做指针算术:将指针强制转换为char *

要执行您要执行的操作,您可以使用位字段说明符,如果需要,您必须添加#pragma pack以禁用填充。
但我真正做的只是使用cast-to-char-pointer技巧 - 一个例子:

#include <stdio.h>
#include <stddef.h>

struct tst
{
    char a;
    int b;
};

int main ( void )
{
    char a;
    int b;
    void *p;
    struct tst tst= {.a = 'q', .b = 1};
    p = &tst;
    //deref((cast  void) add offset)
    a = *(((char *)p) + offsetof(struct tst, a));
    b = *(((char *)p) + offsetof(struct tst, b));
    printf ("%c, %d\n", a, b);
    return 0;
}

然后,输出是:

q, 1