2014-06-08 11 views
20

Dưới đây là một ví dụ mã sau đó là câu hỏi của tôi:Tuyên bố gán cấu trúc C này có hợp pháp không?

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

struct st { 

    char stringField[100]; 
    int intField; 
}; 

typedef struct st st; 

void test(st *parameterStruct) 
{ 
    st localStruct; 
    strcpy(localStruct.stringField, "HELLO"); 
    localStruct.intField = 5; 

    *parameterStruct = localStruct; 
} 

int main() 
{ 
    st myStruct; 
    strcpy(myStruct.stringField, "XXX"); 
    myStruct.intField = 9; 

    printf("%s,%i\n", myStruct.stringField, myStruct.intField); 

    test(&myStruct); 

    printf("%s,%i\n", myStruct.stringField, myStruct.intField); 

    return 0; 
} 

OUTPUT:

XXX,9 
HELLO,5 

Tôi đã suy nghĩ rằng kể từ khi cấu trúc 'localStruct' được tạo ra bên trong một hàm (KHÔNG sử dụng malloc) nó có phạm vi địa phương và do đó các vị trí bộ nhớ mà nó được lưu trữ được tự do để được ghi đè khi chức năng ngừng thực hiện. Tuy nhiên, tôi đã thử chạy chương trình mẫu này và nó được thực thi mà không có vấn đề gì. Tôi đã suy nghĩ rằng các báo cáo in thứ hai sẽ in gibberish vào màn hình kể từ khi tôi được giao 'myStruct' để biến địa phương 'localStruct' (so với 'localStruct' được tự động phân bổ). Tôi biết nếu 'localStruct' đã được tạo ra bằng cách sử dụng malloc sẽ không có vấn đề như vậy.

Câu hỏi của tôi: là gán biến cấu trúc 'myStruct' (biến cục bộ không động) cho y bằng cách sử dụng con trỏ trong kiểm tra hàm không sao và an toàn để làm? Tôi hy vọng rằng câu hỏi là rõ ràng.

+7

Câu hỏi bằng văn bản với SSCCE, bạn tốt sir xứng đáng được +1. –

+0

(Chỉ nitpick: có lẽ tiêu đề có thể được cải thiện thành cái gì đó ít chung hơn?) – usr2564301

Trả lời

9

Chuyển nhượng luôn là bản sao.

Nếu bạn đã làm điều gì đó như *x = &y (giả sử các loại phù hợp - nếu tham số được khai báo là st** x, ví dụ), bạn sẽ được sao chép địa chỉ của y, nhưng kể từ khi y sẽ đi ra khỏi phạm vi sớm, chuyển nhượng mà có không an toàn, như bạn sợ.

Nhưng kể từ khi bạn đang làm *x = y thay vì (nơi tham số được khai báo st* x), bạn đang sao chép nội dung của y-*x, vì vậy ngay cả sau khi y đi ra khỏi phạm vi, dữ liệu được lưu trữ trong *x nên có giá trị.

+4

Tôi nghĩ bạn có nghĩa là 'x = & y' không' * x = & y'. Ít nhất nó phù hợp với câu hỏi IMO tốt hơn. Vâng, trừ khi bạn có nghĩa là 'x' là một con trỏ đến một con trỏ. – luk32

+0

@ luk32 Đúng, nhưng nó sẽ không thay đổi địa chỉ cho biểu thức bên ngoài, điều này sẽ không chứng minh được thực tế rằng biểu thức được gán nằm ngoài phạm vi. Đó là lý do tại sao tôi (không thoải mái) handwaved nó với "giả định các loại đã được hợp lệ". –

+2

Yea, điều đó đúng với ví dụ * không hoạt động như mong đợi * nó sẽ cần phải là 'test (st ** x)'. Đó là một chút bối rối ở dạng 1. – luk32

7

Có. Nó an toàn.

Khi bạn gán:

*x = y; 

Các thành viên của y được sao chép vào các thành viên tương ứng của *x. Nó hoạt động như thể bạn đã làm một thành viên để sao chép thành viên.

1

C cho phép gán cấu trúc. Hai cấu trúc có thể được gán nếu chúng thuộc loại tương thích. Hai cấu trúc được khai báo cùng một lúc tương thích và cấu trúc được khai báo sử dụng cùng một "thẻ cấu trúc" hoặc cùng tên kiểu cũng tương thích.

Trong ví dụ bạn đã cung cấp, cả *xy được khai báo sử dụng cùng tên kiểu cấu trúc st, cả hai đều tương thích và do đó việc gán *x = y là hợp pháp. Vì st x trong main tạo cấu trúc thuộc loại hoàn chỉnh, chuyển địa chỉ của nó đến một hàm là hợp pháp. Trong chức năng của bạn, nhiệm vụ *x = y chỉ cần sao chép nội dung của biến cục bộ y sang *x và thay đổi này thành *x vẫn tồn tại và được phản ánh đến x trong main.

Các vấn đề liên quan