2011-12-15 44 views
5

Xét đoạn mã sau:C - Return một con trỏ char mà không malloc

char* pointerTesting(void) { 

    char* test = "hello"; 
    return test; 
} 

int main() { 

    char* string = pointerTesting(); 
    printf("string: %s\n", string); 
} 

này không có vấn đề biên dịch và chạy. Tuy nhiên, trong sự hiểu biết của tôi, điều này sẽ không hoạt động, vì bộ nhớ được cấp cho con trỏ test nằm trên ngăn xếp và nó bị phá hủy khi trở về chính.

Vì vậy, câu hỏi đặt ra là, làm cách nào để quản lý hoạt động mà không có malloc trong hàm pointerTesting()?

+3

Xem http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-go và một loạt các câu hỏi tương tự về chủ đề này trên stackoverflow. – jman

+0

Con trỏ * được cấp phát trên ngăn xếp (để triển khai điển hình), nhưng bạn không trả lại con trỏ, chỉ sao chép nếu giá trị của nó. Nó tương tự như 'int n = 42; return n; '. Đó là việc phân bổ những gì nó trỏ đến đó là có liên quan. –

Trả lời

13

Trong trường hợp này, chuỗi "hello" được lưu trữ trong bộ nhớ chung *. Vì vậy, đã được phân bổ.

Vì vậy, nó vẫn hợp lệ khi bạn trở về từ hàm.

Tuy nhiên, nếu bạn đã làm điều này:

char test[] = "hello"; 
return test; 

Sau đó không, nó sẽ không làm việc. (hành vi không xác định) Trong trường hợp này, chuỗi thực sự là một mảng cục bộ - không còn tồn tại khi hàm trả về.

* Mặc dù điều này thường xảy ra, tiêu chuẩn không nói rằng nó phải được lưu trữ trong bộ nhớ chung.
Nhưng phần quan trọng là tuổi thọ của chuỗi ký tự là thời lượng của toàn bộ chương trình. (xem ý kiến)

+0

Tôi sẽ hạnh phúc hơn nếu câu trả lời của bạn đề cập rằng '" hello "' nằm trong bộ nhớ toàn cục do một tai nạn thực hiện và _not_ do hành vi được đăng ký theo bất kỳ tiêu chuẩn nào. – sarnold

+0

@ sarnold Đồng ý, tôi có nên thay đổi nó thành "* thường * được lưu trữ trong bộ nhớ toàn cầu" không? Hoặc tôi nên nói "được lưu trữ * ở nơi khác *"? – Mysticial

+0

Tôi thích dấu hoa thị bạn có ngay bây giờ. :) Cảm ơn! – sarnold

2

Bí quyết là bộ nhớ được tham chiếu bằng kiểm tra không nằm trong ngăn xếp như bạn mong đợi. Xem String literals: Where do they go? để biết một số giải thích.

5

Bạn đang trở về giá trị của test, đó là địa chỉ của ký tự đầu tiên trong chuỗi literal "hello" (trong đó, giống như tất cả xâu, được lưu giữ như một mảng của char theo cách như vậy mà nó có sẵn trong suốt thời gian của chương trình). Nếu bạn đang cố gắng trả lại địa chỉ của test để sử dụng sau này, thì vâng, bạn sẽ gặp sự cố.

Bây giờ đoạn sau sẽ không công việc:

char *pointerTesting(void) 
{ 
    char test[] = "hello"; 
    return test; 
} 

Trong trường hợp này, bạn đang cố gắng để trả lại địa chỉ của phần tử đầu tiên trong một đối tượng mảng đó là địa phương để các chức năng, mà sẽ không hợp lệ khi chức năng thoát. Hãy nhớ rằng trong hầu hết các ngữ cảnh, một biểu thức kiểu "mảng phần tử N của T" sẽ được thay thế bằng một biểu thức kiểu "con trỏ tới T" có giá trị là địa chỉ của phần tử đầu tiên trong mảng.

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