我正在开发一个程序,我们试图将结构体指针转换为字符指针,以便稍后可以在其他函数中使用它,我听到有人说,如果结构体的元素对齐,那么我们可以这样做类型转换并对其进行处理,但需要帮助来理解这个概念:
示例:
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 中的结构填充和对齐有关。当您有一个结构时,编译器可能会在成员之间插入填充以在内存中对齐它们。这种填充确保每个成员从其大小的倍数的地址开始,这可以提高内存访问的性能。
现在,将 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;
}
修复概述:内存分配问题和字符串分配当然也会释放分配的内存,以防止发生内存泄漏