在c中将struct指针转换为char指针

问题描述 投票:0回答:1

我正在开发一个程序,我们试图将结构体指针转换为字符指针,以便稍后可以在其他函数中使用它,我听到有人说,如果结构体的元素对齐,那么我们可以这样做类型转换并对其进行处理,但需要帮助来理解这个概念:

示例:

Structure S1{
    char *first_name;
    char *last_name;
    uint16_t first_len;
    uint16_t last_len;
    uint32_t attrs;
    op status; -> this is a enum
};

Structure S2{
uint16_t a;
uint16_t b;
uint32_t c;
int8_t d; 
};

S2 可以转换为 char* 但 S1 不能。

下面是我想使用的程序(这是为了将一个结构内容深入复制到另一个结构),但我为此遇到了分段错误

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

#define ARW_SIZE 3

typedef struct sample_struct{
    char *first_name;
    char *last_name;
    int first_len;
    int last_len;
    int attrs;
    int status;
}sample;

typedef struct sample_header{
    int first_len;
    int last_len;
    int attrs;
}header;

int copy(sample *src, char *dst){
    header *header_ptr = (header *)dst;

    header_ptr->first_len = src->first_len;
    header_ptr->last_len = src->last_len;
    header_ptr->attrs = src->attrs;
    dst += sizeof(header);
    memmove(dst, src->first_name, src->first_len);

    if (header_ptr->last_len) {
        dst += src->last_len;
        memmove(dst, src->last_name, src->last_len);
    }

    return sizeof(header) + header_ptr->first_len + header_ptr->last_len;
}

int func1(sample **arw){
    sample *s1 = malloc(sizeof(sample));
    s1->first_name = malloc(sizeof(char));
    s1->last_name = malloc(sizeof(char));
    s1->first_name = "sai";
    s1->last_name = "sankalp";
    s1->first_len = 3;
    s1->last_len = 8;
    s1->attrs = 6;
    s1->status = 1;

    sample *s2 = malloc(sizeof(sample));
    s2->first_name = malloc(sizeof(char));
    s2->last_name = malloc(sizeof(char));
    s2->first_name = "sai1";
    s2->last_name = "sankalp1";
    s2->first_len = 4;
    s2->last_len = 9;
    s2->attrs = 64;
    s2->status = 12;

    *arw = malloc(sizeof(sample) * ARW_SIZE);

    arw += copy(s1, (char *)*arw);
    
    return 1;


}

int main(){

    printf("Hello World!\n");


    sample *res = NULL;

    func1(&res);
   
    printf("Fname: %s, Lname: %s, Fname_Len: %d, Lname_Len: %d, attrs: %d, status: %d\n", res->first_name, res->last_name, res->first_len, res->last_len, res->status);

    return 0;
}
c pointers struct
1个回答
0
投票

您所指的概念与 C 中的结构填充和对齐有关。当您有一个结构时,编译器可能会在成员之间插入填充以在内存中对齐它们。这种填充确保每个成员从其大小的倍数的地址开始,这可以提高内存访问的性能。

现在,将 struct 指针转换为 char 指针以及反之亦然的问题与此填充有关。如果结构体的成员之间存在填充,则结构体的大小可能大于其成员大小的总和。此填充是由编译器出于对齐目的而添加的。

在你的例子中:

struct S1 {
    char *first_name;
    char *last_name;
    uint16_t first_len;
    uint16_t last_len;
    uint32_t attrs;
    enum op status;
};

struct S2 {
    uint16_t a;
    uint16_t b;
    uint32_t c;
    int8_t d; 
};

S1
结构体包含指针
(char*)
32-bit integer (uint32_t)
,由于对齐要求,这可能会导致成员之间出现填充。另一方面,
S2
结构由大小自然对齐的成员组成,不需要额外的填充。

要将 struct 指针转换为 char 指针,反之亦然,通常会使用“类型双关”的概念。但是,使用包含指针且可能具有填充的结构执行此操作需要谨慎。如果结构包含重要类型或者布局不是您所期望的,您可能会遇到问题。

如果出于通信或存储目的需要序列化/反序列化结构,请考虑使用适当的序列化技术或库。另外,如果您需要确保特定的内存布局,您可以使用特定于编译器的指令来控制打包和对齐。您添加的程序存在一些与字符串内存分配相关的问题 因此,不要使用

malloc(sizeof(char))
进行字符串分配,而是使用
malloc(strlen(str) + 1)
为字符串和空终止符分配足够的空间。使用
strcpy
strncpy
来复制字符串,而不是直接分配它们。
copy
函数应该将目标结构作为参数,而不是
char*
。现在固定代码版本

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

#define ARW_SIZE 3

typedef struct sample_struct {
    char *first_name;
    char *last_name;
    int first_len;
    int last_len;
    int attrs;
    int status;
} sample;

typedef struct sample_header {
    int first_len;
    int last_len;
    int attrs;
} header;

int copy(sample *src, sample *dst) {
    header *header_ptr = (header *)dst;

    header_ptr->first_len = src->first_len;
    header_ptr->last_len = src->last_len;
    header_ptr->attrs = src->attrs;

    dst->first_name = malloc(src->first_len + 1);
    strcpy(dst->first_name, src->first_name);

    if (header_ptr->last_len) {
        dst->last_name = malloc(src->last_len + 1);
        strcpy(dst->last_name, src->last_name);
    }

    return sizeof(header) + header_ptr->first_len + header_ptr->last_len;
}

int func1(sample **arw) {
    sample *s1 = malloc(sizeof(sample));
    s1->first_name = malloc(strlen("sai") + 1);
    strcpy(s1->first_name, "sai");
    s1->last_name = malloc(strlen("sankalp") + 1);
    strcpy(s1->last_name, "sankalp");
    s1->first_len = 3;
    s1->last_len = 8;
    s1->attrs = 6;
    s1->status = 1;

    sample *s2 = malloc(sizeof(sample));
    s2->first_name = malloc(strlen("sai1") + 1);
    strcpy(s2->first_name, "sai1");
    s2->last_name = malloc(strlen("sankalp1") + 1);
    strcpy(s2->last_name, "sankalp1");
    s2->first_len = 4;
    s2->last_len = 9;
    s2->attrs = 64;
    s2->status = 12;

    *arw = malloc(sizeof(sample) * ARW_SIZE);

    arw += copy(s1, *arw);

    return 1;
}

int main() {
    printf("Hello World!\n");

    sample *res = NULL;

    func1(&res);

    printf(
        "Fname: %s, Lname: %s, Fname_Len: %d, Lname_Len: %d, attrs: %d, status: %d\n",
        res->first_name, res->last_name, res->first_len, res->last_len, res->attrs, res->status
    );

    // Free allocated memory
    free(res->first_name);
    free(res->last_name);
    free(res);

    return 0;
}

修复概述:内存分配问题和字符串分配当然也会释放分配的内存,以防止发生内存泄漏

© www.soinside.com 2019 - 2024. All rights reserved.