类型结构指针

时间:2016-01-28 11:44:38

标签: c pointers struct

嗨伙计们。我正在使用名为Pointers in C: A Hands on Approach的书来学习结构和指针,在第107页,我遇到了一个结构类型转换的不完整的例子。我试图通过实现函数receivedata(),添加标题并进行一些更改来使其工作。
这是完整的代码:

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

struct signature
{
    char  sign;
    char version;
};

struct id
{
    char id;
    char platform;
};

struct data
{
    struct id idv;
    struct signature sig;
    char data[100];
};

static void receivedata(struct data *d);
static struct signature *extractsignature(struct data *d);
static struct id *extractid(struct data *d);

int main(int argc, char *argv[])
{
/* Actual line in book is :
*  struct data *img; with no memory allocation or assignment to NULL.
*  Had errors so i allocated memory on the heap before passing the value to 
*  Receivedata(); */
    struct data *img = malloc(sizeof(struct data));

    receivedata(img);

/* Actual line in book is :
 *   struct id *idval = extractid(&img);
 *   struct signature *sig = extractsignature(&img);
 * This is obviously erroneous because &img is a pointer 
 * to a pointer (struct data**) which is not the data type for 
 * the extract functions' argument */
    struct id *idval = extractid(img);
    struct signature *sig = extractsignature(img);

    printf("For signature:\n");
    printf("sign = %c", sig->sign);
    printf(" version = %c\n\n", sig->version);

    printf("For id:\n");
    printf("id = %c", idval->id);
    printf(" platform = %c", idval->platform);

    printf("\ndata = %s", img->data);

    return 0;
}

static struct signature *extractsignature(struct data *d)
{
    struct signature *sig = (struct signature *)d;
    return sig;
}

static struct id *extractid(struct data *d)
{
    struct id *idv = (struct id *)d;
    return idv;
}

static void receivedata(struct data *d)
{
    struct data *dptr = d;
    char *ch = "CODING IS COOL!";

    dptr->sig.sign = 's';
    dptr->sig.version = '1';

    dptr->idv.id = 'i';
    dptr->idv.platform = 'p';

    strncpy(dptr->data, ch, strlen(ch));

    return;
}

我想要理解的是函数extractid()extraxtsignature()内部的转换,因为我们似乎正在转换struct data *以便检索其各个成员。我运行程序,我得到的是sig成员和id成员的struct data的第一个成员的值。以下是struct idstruct data首先出现时的输出:

For signature:
sign = i version = p

For id:
id = i platform = p
data = CODING IS COOL!

struct signature是第一个元素时

For signature:
sign = s version = 1

For id:
id = s platform = 1
data = CODING IS COOL!

最后,当char data[100]是第一个元素时:

For signature:
sign = C version = O

For id:
id = C platform = O
data = CODING IS COOL!

请您解释一下这种类型的铸件,何时使用它以及最佳实践。非常感谢你。

1 个答案:

答案 0 :(得分:1)

struct data
{
    struct id idv;
    struct signature sig;
    char data[100];
};

对于上面的定义,下面的extractid函数有效,并且会得到正确的结果。

static struct id *extractid(struct data *d)
{
    struct id *idv = (struct id *)d;
    return idv;
}

这是因为struct idstruct data的第一个成员。因此,当您struct data *d时,d指向struct data的起始地址,并且与第一个成员struct id的起始地址相同。

因此,如果您要为结构的第一个成员进行强制转换,那么根据您在上面提供的代码,它是正确的。