2011-08-16 46 views
6

Đây là một câu hỏi dựa trên câu trả lời từ câu hỏi:Char Mảng VS Char *

const char myVar* vs. const char myVar[]

const char* x = "Hello World!"; 
const char x[] = "Hello World!"; 

Tôi hiểu sự khác biệt bây giờ, nhưng những câu hỏi mới của tôi là:

(1) gì xảy ra với chuỗi "Hello World" trong dòng đầu tiên nếu tôi gán lại x? Không có gì sẽ được trỏ đến nó bởi thời điểm đó - nó sẽ bị phá hủy khi phạm vi kết thúc?

(2) Ngoài const-ness, các giá trị trong hai ví dụ khác nhau được lưu trữ trong bộ nhớ bằng trình biên dịch như thế nào?

Trả lời

9

Đặt "Hello World!" vào mã của bạn khiến trình biên dịch bao gồm chuỗi đó trong tệp thi hành đã biên dịch. Khi chương trình được thực hiện chuỗi được tạo ra trong bộ nhớ trước khi gọi đến main và, tôi tin rằng, ngay cả trước khi cuộc gọi lắp ráp đến __start (đó là khi khởi tạo tĩnh bắt đầu chạy). Nội dung của char * x không được phân bổ bằng cách sử dụng new hoặc malloc hoặc trong ngăn xếp của main và do đó không thể không được phân bổ.

Tuy nhiên, một char x[20] = "Hello World" được khai báo trong một hàm hoặc phương thức được phân bổ trên ngăn xếp và trong phạm vi thực tế, sẽ có hai bản sao của "Hello World" trong bộ nhớ - một bản sao được thực thi đệm được cấp phát.

+0

const char x [] là nghĩa vụ phải sao chép dữ liệu vào ngăn xếp tuy nhiên. –

-1
  1. Chính thức trong cả hai trường hợp chuỗi "Hello World!" được phân bổ trong bộ nhớ tĩnh như là một chuỗi liền kề của char, do đó, bộ nhớ không được cấp phát động để đòi lại cũng không bất kỳ trường lớp để tiêu diệt;
  2. Cả hai x s sẽ được cấp phát trong bộ nhớ tĩnh hoặc trên ngăn xếp, tùy thuộc vào vị trí chúng được xác định. Tuy nhiên con trỏ sẽ được khởi tạo để trỏ đến chuỗi "Hello World!" tương ứng, trong khi mảng sẽ được khởi tạo bằng cách sao chép chuỗi ký tự trực tiếp vào nó.

Về lý thuyết trình biên dịch tự do đòi lại bộ nhớ của cả hai chuỗi ký tự khi không có cách nào truy cập chúng; trong thực tế, cái đầu tiên không thể được khai hoang, vì bộ nhớ tĩnh thường vẫn được cấp phát cho chương trình cho đến khi nó kết thúc; mặt khác nếu mảng được cấp phát trên ngăn xếp thứ hai có thể thậm chí không được cấp phát, vì trình biên dịch có thể sử dụng các phương tiện khác để đảm bảo mảng được khởi tạo đúng cách và bộ nhớ mảng sẽ được khôi phục khi nó hết phạm vi.

+0

Ngoài ra, làm sizeof (x) với con trỏ sẽ dẫn đến 4 (hoặc 8 trong mã 64bit), trong khi sizeof (x) với mảng sẽ dẫn đến số byte chứa mảng. – Matthew

+2

-1: Chúng không được phân bổ theo cùng một cách. Ví dụ đầu tiên là một con trỏ đến bộ nhớ tĩnh. Ví dụ thứ hai là một mảng không tĩnh có nội dung được khởi tạo với '" Hello world! "'. –

+2

Tôi nghĩ ý tưởng đằng sau const char x [] là mảng nằm trên ngăn xếp, không đơn giản chỉ là một con trỏ, và "Hello World!" được sao chép vào nó.Điều này có thể được tối ưu hóa, nhưng ý tưởng này hoàn toàn khác với một con trỏ đơn giản. –

4

Trình biên dịch lưu trữ tệp đầu tiên trong phần bộ nhớ có tên RODATA (dữ liệu chỉ đọc). Miễn là chương trình vẫn đang chạy, bộ nhớ vẫn giữ giá trị ban đầu của nó.

Thứ hai được lưu trữ giống như bất kỳ mảng nào khác - trên ngăn xếp. Giống như bất kỳ biến cục bộ nào khác, nó có thể bị ghi đè khi phạm vi của nó kết thúc.

+0

'Miễn là chương trình vẫn đang chạy, bộ nhớ vẫn giữ giá trị ban đầu của nó.' Tức là, phạm vi của chuỗi là phạm vi chương trình, không phải là của hàm. –