Reputation: 63
Is there any way to copy two different structure types, with similar content, without copying variable by variable?
For example, read a file, save to pessoa
and copy to xpessoa
assuming email
is 'not defined'
.
struct pessoa {
char nome[50];
char telefone[20];
struct{
int dia,mes,ano;
}data_nasc;
};
struct xpessoa {
char nome[50];
char telefone[20];
struct{
int dia,mes,ano;
}data_nasc;
char email[50];
};
Upvotes: 1
Views: 235
Reputation: 17513
If you cannot change the "extended" structure to include the "base" structure as its initial member, the only legal way to copy the whole "base" structure into the "extended" structure is to define a union containing both structure types as members.
Quoting C11 section 6.5.2.3 (Structure and union members) paragraph 6:
One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.
So you can define a union containing members of type struct pessoa
and struct xpessoa
and access the common parts from either member:
union upessoa {
struct pessoa p;
struct xpessoa xp;
};
int somefunc(void) {
union upessoa a = { .p = {"Fred", "555-5555", {1, 2, 3} };
// This is legal because data_nasc is part of the common initial sequence
return a.xp.data_nasc.ano;
}
In my experience, a lot of code ignores this requirement for the structures to be members of a union, and assumes that if any two structures share a common initial sequence, the common initial sequence can be copied between objects of the different structure types; but this results in undefined behavior - it might work, but it isn't portable.
Upvotes: 0
Reputation: 564
If for some reason you are not allowed to change either structure than, you could do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct pessoa {
char nome[50];
char telefone[20];
struct{
int dia,mes,ano;
}data_nasc;
};
struct xpessoa {
char nome[50];
char telefone[20];
struct{
int dia,mes,ano;
}data_nasc;
char email[50];
};
int main() {
struct pessoa p = {"John", "111-222", {1, 2, 3}};
struct xpessoa xp = { .email = "[email protected]"};
memcpy(&xp, &p, sizeof(p));
printf("name: %s email: %s \n", xp.nome, xp.email);
return 0;
}
However as @dasblinkenlight said, this would be a very dangerous approach, since it would require to manually track the both structures.
Upvotes: 1
Reputation: 727127
An approach that is guaranteed to work is to embed the pessoa
into xpessoa
, like this:
struct xpessoa {
pessoa p;
char email[50];
};
This approach protects your code from undefined behavior in case pessoa
layout is changed, because xpessoa
no longer mirrors its layout.
Upvotes: 6