C 类型转换为包含另一个结构ptr的结构

C 类型转换为包含另一个结构ptr的结构,c,casting,segmentation-fault,C,Casting,Segmentation Fault,我的数据结构如下所示: typedef struct struct2 { uint8_t num; uint8_t action; uint8_t id; } struct2_t; typedef struct struct1 { uint8_t title; struct2_t* content; } struct1_t; 我给一个结构指针分配了一个内存空间,并打印出了值 void main(){ const uint8_t msg[5] = {

我的数据结构如下所示:

typedef struct struct2 {
  uint8_t  num;
  uint8_t  action;
  uint8_t  id;
} struct2_t;

typedef struct struct1 {
  uint8_t  title;
  struct2_t* content;
} struct1_t;
我给一个结构指针分配了一个内存空间,并打印出了值

void main(){

    const uint8_t msg[5] = {
            5, 4, 3, 2, 1
    };

    struct1_t *req = NULL;
    req = (struct1_t *)msg;

    printf("%d ", req->title);
    printf("%d ", req->content->num);
    printf("%d ", req->content->action);
    printf("%d ", req->content->id);

}
结果是: 5 5 4 3 而我以为是5432

此外,在另一个地方,我复制缓冲区中的内容并做类似的事情

void main(){

    const uint8_t msg[5] = {
            5, 4, 3, 2, 1
    };

    uint8_t *test = NULL;
    test = (uint8_t*)malloc(5 + 1);
    memset((test), 0x00, 5);
    memcpy(test, msg , 5);

    struct1_t *req = NULL;
    req = (struct1_t *)test;

    printf("%d ", req->title);
    printf("%d ", req->content->num);
    printf("%d ", req->content->action);
    printf("%d \n", req->content->id);
}
但这次我无法访问struct2\u t指针

五, 分段故障(堆芯转储)


谁能告诉我我错过了什么?感谢您的帮助

您从未初始化
内容
,因此您会得到未定义的行为。您需要执行以下操作:

/* ... */

    req = (struct1_t *)msg;
    req->content = (struct2_t *)&msg[1];

    printf("%d ", req->title);

/* ... */

Typepunning不是递归的。

代码中有两个FAW,首先在结构1中使用指向结构2的指针,但在结构1实例的内存中填充数据,因此其中一个值被视为指针。 第二,您必须考虑结构内数据的对齐方式。编译器根据数据的类型和目标体系结构放置数据,并用填充字节填充空格。如果数据是4字节对齐的,32位体系结构通常会更好地访问数据,因此编译器会将struct1(或struct1指针)移动到下一个4字节对齐的地址。所以你的代码中有

0xYYYYYYYY+00 struct1.title (byte0)
0xYYYYYYYY+01 padding byte0
0xYYYYYYYY+02 padding byte1
0xYYYYYYYY+03 padding byte2
0xYYYYYYYY+04 struct1.struct2*
如果您纠正了指针问题:那么您有

0xYYYYYYYY+00 struct1.title (byte0)
0xYYYYYYYY+01 padding byte0
0xYYYYYYYY+02 padding byte1
0xYYYYYYYY+03 padding byte2
0xYYYYYYYY+04 struct1.struct2.num
0xYYYYYYYY+05 struct1.struct2.action ( here is no padding,as the data iself is u8)
0xYYYYYYYY+06 struct1.struct2.id( here is one paddingbyte,as the data iself is u8, but at the end of the structure).

一般来说,我建议不要以这样的方式初始化SRTUCT,因为您必须考虑编译器的对齐逻辑,这可能有点棘手。

当您使用“<代码> DOT/<代码>(<代码> ./COD> >)具有结构的操作符和何时使用<代码>箭头< /代码>时,您显然缺少的是一个清晰的理解。(

->
)运算符

规则很简单。如果有
结构
,则使用
运算符访问其成员。如果有指向结构的
指针,则使用
->
箭头运算符访问其成员。如果有包含指向结构
指针的
结构
,则使用其中一个

下面的示例应该说明这一点,并提供使用
内容
指针指向具有自动存储
s2
的结构和存储在动态分配内存“s3”中的结构的示例

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

enum { MAXL = 128, MAXC = 512 };

typedef struct struct2 {
uint8_t  num;
uint8_t  action;
uint8_t  id;
} struct2_t;

typedef struct struct1 {
uint8_t  title;
struct2_t *content;
} struct1_t;

int main (void) {

    struct2_t s2 = { 5, 4, 3 }, *s3 = NULL;
    struct1_t s1 = { 2, &s2 };  /* content initialized to s2 */

    /* using address of s2 as content */
    printf ("\n title  : %" PRIu8 "\n"
            " num    : %"   PRIu8 "\n"
            " action : %"   PRIu8 "\n"
            " id     : %"   PRIu8 "\n", s1.title, 
            s1.content->num, s1.content->action, 
            s1.content->id);

    /* dynamic allocation of s3 */
    if (!(s3 = calloc (1, sizeof *s3))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 0;
    }

    s3->num    = 8;  /* assignment of values to s3 */
    s3->action = 7;
    s3->id     = 6;
    s1.content = s3; /* update content pointer to s3 */

    /* using address of s3 as content */
    printf ("\n title  : %" PRIu8 "\n"
            " num    : %"   PRIu8 "\n"
            " action : %"   PRIu8 "\n"
            " id     : %"   PRIu8 "\n", s1.title, 
            s1.content->num, s1.content->action, 
            s1.content->id);

    free (s3);  /* don't forget to free all memory you allocate */

    return 0;
}

查看示例并让我知道您是否还有其他问题,或者如果我遗漏了您问题的一部分,请让我也知道。

+1用于区分typedef name和struct标记,以及将_t约定与标准库一致地应用。(但main应返回
int
)我的猜测是,您还没有发现编译器为提供对齐而添加到结构中的填充差异。您还需要查看
man offsetof
,以了解确定编译器应用的填充的方法。与标题中的断言相反,您没有声明包含其他结构的结构。您声明了一个包含指向另一个结构的指针的结构。这完全不是一回事。感谢您指出运行的类型不是递归的,但基于上述其他答案,我可能无法执行(struct2_t*)&msg[1]因为我的结构中存在填充。感谢提供清晰的示例。我尝试了初始化的方法,它可以工作。很高兴我能提供帮助。如果您有任何其他问题,请告诉我。祝您编码顺利。感谢您指出填充问题。我还尝试了pack(1),填充问题得到了解决。
$ ./bin/structnested

 title  : 2
 num    : 5
 action : 4
 id     : 3

 title  : 2
 num    : 8
 action : 7
 id     : 6