嗨伙计们。我正在使用名为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 id
中struct 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!
请您解释一下这种类型的铸件,何时使用它以及最佳实践。非常感谢你。
答案 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 id
是struct data
的第一个成员。因此,当您struct data *d
时,d
指向struct data
的起始地址,并且与第一个成员struct id
的起始地址相同。
因此,如果您要为结构的第一个成员进行强制转换,那么根据您在上面提供的代码,它是正确的。