Post-K&R (i.e. in standard C)1 you can just assign them. The function below is just to make the example clear, you would always just assign in-place:
void deepCopyPerson(struct person *target, struct person *src)
{
*target = *src;
}
To elaborate: The char arrays are part of your struct object (true arrays, not only pointers!), and as such are allocated and copied with the object.
In order to satisfy the disbeliefers ;-) I dug around in the standard draft 1570 :
6.5.16 Assignment operators
Semantics
An assignment operator stores a value in the object designated by the left operand. [Followed by type conversion and sequencing considerations which are not relevant here.]
[...]
6.5.16.1 Simple assignment
Constraints
One of the following shall hold:
- the left operand
has an atomic, qualified, or unqualified version of a structure or
union type compatible with the type of the right;
[...]
Semantics
In simple assignment (=), the value of the right operand is converted
to the type of the assignment expression and replaces the value stored
in the object designated by the left operand.
1 The first edition of The C Programming Language, written by Brian W. Kernighan and Dennis M. Ritchie at Bell Labs and published in 1978, is the informal language specification for the first C version, often called "K&R C" after the two authors of the book specifying it (and as a distinction to ANSI C which was specified 10 years later). This first edition of the book contains the following sentence on page 121:
The essential rules are that the only operations that you can perform on a structure are take its address with &, and access one of its members.
In particular, you cannot assign structures. (But they continue "these restrictions will be removed in forth- coming versions".)
Indeed, this was one of the few substantial (as opposed to syntactical) additions to the language in the ANSI version passed 10 years later. Kernighan and Ritchie prepared an accompanying "ANSI C edition" of their book. The sentence, this time on page 129, now reads:
The only legal operations on a structure are copying and assigning to it as a unit, taking its address with &, and accessing its members.
They elaborate:
Copy and assignment include passing arguments to functions and returning values from functions as well.
This equivalence is still true today in the latest C++ standard.
And since we are here in the root canal of C++: The next statement was an apodictic "Structures may not be compared." It is interesting that they added this sentence — obviously, built-in comparison suggested itself after introducing built-in assignment, but was rejected. In my opinion, there was never a good reason for that: If you can assign member-wise, why not compare that way as well? That would do just fine in many cases, and manual comparison is hard to maintain. It took another 30 years to make that possible in C++20 with the spaceship operator which generates all the other comparisons when it is (explicitly) defaulted; indeed, it defaults to member-wise comparison.