Keywords: C Language | Struct Assignment | Memory Copy | Shallow Copy | Deep Copy
Abstract: This paper comprehensively examines the mechanisms and implementation principles of struct assignment in C programming language. By analyzing how compilers handle struct assignment operations, it explains the fundamental nature of memory copying. Detailed discussion covers behavioral differences between simple and complex structs during assignment, particularly addressing shallow copy issues with pointer members. Through code examples, multiple struct copying methods are demonstrated, including member-by-member assignment, memcpy function, and direct assignment operator, with analysis of their advantages, disadvantages, and applicable scenarios. Finally, best practice recommendations are provided to help developers avoid common pitfalls.
Fundamental Principles of Struct Assignment
In C language, the struct assignment operation t2 = t1 is essentially data copying at the memory level. The compiler generates corresponding memory copy instructions based on the size of the struct type. For instances of the same struct type, this assignment operation is completely legal, and the compiler can properly handle the copying of various basic data type members.
How Compiler Handles Different Type Members
The compiler does not need to "know" how to distinguish between specific types like int and strings during struct assignment. The assignment operation is based on direct copying of memory blocks, requiring the compiler only to know the total size and memory layout of the struct. For basic data types such as int, float, char, etc., the assignment operation copies the corresponding memory content bit by bit.
Differences Between Simple and Complex Structs
For simple structs that don't contain pointers, direct assignment works perfectly:
struct SimpleStruct {
int a;
float b;
char c;
};
struct SimpleStruct s1 = {10, 3.14, 'X'};
struct SimpleStruct s2;
s2 = s1; // Complete copy of all members
Shallow Copy Issues with Pointer Members
When a struct contains pointer members, direct assignment only copies the pointer value itself, not the data pointed to by the pointer:
struct ComplexStruct {
char *p;
};
struct ComplexStruct s1, s2;
s1.p = malloc(100);
strcpy(s1.p, "Hello");
s2 = s1; // Only copies pointer, not string data
In this case, s1.p and s2.p point to the same memory block. Modifying one will affect the other, and it becomes difficult to determine which struct instance owns the data.
Comparison of Multiple Struct Copying Methods
Method 1: Member-by-Member Assignment
typedef struct {
char name[63];
int gender;
int age;
float height;
} User;
User user = {"John", 0, 25, 175.5};
User user1;
// Copy each member individually
strncpy(user1.name, user.name, sizeof(user.name));
user1.gender = user.gender;
user1.age = user.age;
user1.height = user.height;
Advantages: Clear code intent, allows special handling for specific members. Disadvantages: Code becomes verbose and error-prone as struct size increases.
Method 2: Using memcpy Function
User user = {"Jane", 1, 30, 165.0};
User user1;
// Use memcpy for memory copying
memcpy(&user1, &user, sizeof(User));
Advantages: Concise code, completes all member copying in one operation. Disadvantages: Cannot handle members requiring special treatment, such as dynamically allocated memory.
Method 3: Direct Assignment Operator
User user = {"Mike", 0, 28, 180.0};
User user1;
// Direct use of assignment operator
user1 = user;
Advantages: Simple and intuitive syntax, compiler automatically handles all copying details. Disadvantages: May produce unexpected shallow copy behavior for structs containing pointers.
Assignment Characteristics of Struct Pointers
It's important to note that assignment of struct pointers is fundamentally different from assignment of struct instances:
User *ptr1, *ptr2;
User user = {"Sarah", 1, 35, 170.0};
ptr1 = &user;
ptr2 = ptr1; // Only copies pointer value, not struct data
In this case, ptr1 and ptr2 point to the same struct instance. Any modification through one pointer will affect the other.
Best Practice Recommendations
1. For simple structs without pointers, prioritize using direct assignment operator for concise and efficient code.
2. For structs containing pointers to dynamically allocated memory, implement deep copy functions to manually copy the data pointed to by pointers.
3. When passing structs across functions, consider using pointer passing to avoid unnecessary copying overhead.
4. For large structs, using memcpy may be more efficient than member-by-member assignment, but pay attention to memory alignment issues.
Conclusion
Struct assignment operations in C provide convenient data copying mechanisms, but their underlying implementation is based on simple memory copying. Developers need to fully understand the limitations of this mechanism, especially when dealing with complex structs containing pointers. By choosing appropriate copying strategies, program correctness and performance can be ensured.