2010-10-17 4 views
5
#include <stdio.h> 

const int str[1000] = {0}; 

int main(void) 
{ 
    printf("arr is %d\n", str[0]); 
    return 0; 
} 

Có đầu ra sau đây:Biến được khởi tạo toàn cục được khai báo là "const" chuyển đến phân đoạn văn bản, trong khi các biến được khai báo "Tĩnh" đi đến phân đoạn dữ liệu. Tại sao?

[-exercises/adam/stack2]:size a.out 
    text data  bss  dec  hex filename 
    5133  272  24 5429 1535 a.out 

Trong đó:

#include <stdio.h> 

static int str[1000] = {0}; 

int main(void) 
{ 
    printf("arr is %d\n", str[0]); 
    return 0; 
} 

Có đầu ra sau đây:

[-exercises/adam/stack2]:size a.out 
    text data  bss  dec  hex filename 
    1080 4292  24 5396 1514 a.out 

Khi mảng được uninitialized - nó một lần nữa đi vào văn bản phân đoạn cho "const" và BSS cho "tĩnh".

Biến là toàn cầu và có thể truy cập được từ bất kỳ nơi nào trong tệp thực thi, là một phần của (vì không có "tĩnh"), nhưng với biến của nó, tôi không biết tại sao nó được đặt trong phân đoạn văn bản thay vì dữ liệu phân đoạn?

+0

+1: Câu hỏi hay. Bạn có thể muốn mở rộng nó thành 'static const'. – Arun

Trả lời

6

Bạn đang bối rối. Không có sự phân tách giữa conststatic; hai là độc lập. Giả sử tất cả dữ liệu được khởi tạo, cả hai static const và bên ngoài (toàn cầu) const sẽ ở trong text và cả hai không const -qualified static và không phải là const bên ngoài đủ điều kiện sẽ đi theo số data.

Đối với bss, các định dạng nhị phân hiện đại như ELF thực sự có riêng biệt bss cho dữ liệu không đổi và không liên tục. Đầu ra của lệnh size không hiển thị nó.

+0

Bạn nói đúng. Cảm ơn bạn đã làm rõ. – helpmelearn

3

Để cho phép bảo vệ bộ nhớ hoạt động. Bất kỳ cố gắng để viết vào một const sẽ kích hoạt một segfault.

1

Khi bạn khai báo biến số const, bạn đang nói trình biên dịch rằng bạn không bao giờ có ý định thay đổi giá trị của nó. Mặt khác, với khai báo static được thực hiện ở phạm vi tệp, bạn đang nói với trình biên dịch rằng biến đó là riêng đối với đơn vị biên dịch nó đã được khai báo, nhưng các hàm trong đơn vị biên dịch đó vẫn được phép sửa đổi biến này.

Như Oli đề cập trong số answer của mình, định vị biến số const trong phân đoạn text cho phép hệ thống thực thi bảo vệ quyền truy cập bộ nhớ. Ngoài ra, hãy xem xét một hệ thống nhúng, trong trường hợp đó phân đoạn text thường được ghi vào flash và do đó không thể sửa đổi được. Các phân đoạn data, bss v.v. được đặt trong RAM và cho phép sửa đổi chúng.

7

Từ Kernighan & Ritchie:

tĩnh là một specifier lớp lưu trữ. Các thông số lớp lưu trữ khác là: tự động, đăng ký, extern & typedef. Trình xác định tĩnh cung cấp cho lớp đối tượng được khai báo là đối tượng tĩnh. Khai báo tĩnh, được áp dụng cho một biến hoặc hàm ngoài, giới hạn phạm vi của đối tượng đó với phần còn lại của tệp nguồn đang được biên dịch. Các đối tượng tĩnh có thể là cục bộ đối với một khối hoặc bên ngoài đối với tất cả các khối, nhưng trong trường hợp giữ lại giá trị của chúng trên lối ra từ và reentry đến hàm và khối.

Trong khi đó,

const là một loại vòng loại. Loại vòng loại loại khác là dễ bay hơi. Mục đích của của const là thông báo các đối tượng có thể được đặt trong bộ nhớ chỉ đọc và có thể để tăng cơ hội tối ưu hóa .

Tôi cho rằng người ta có thể phỏng đoán rằng cả hai từ khóa này đều phục vụ cho các mục đích khác nhau; của các biến số const đang ở trong text/code segment là khá rõ ràng so với mục đích của nó.

+2

+1 để trích dẫn K & R –

1

Bằng cách đặt dữ liệu const vào phần văn bản, trình biên dịch đang cố gắng thực thi constness.

Hãy nhớ rằng phần TEXT được nạp vào các trang bộ nhớ được đánh dấu chỉ đọc trong các bảng trang MMU. Điều này là để bảo vệ chống tham nhũng tình cờ của mã. Bằng cách đặt dữ liệu const trong cùng một khu vực, làm cho dữ liệu đó chỉ đọc. Bất kỳ ghi vào dữ liệu này sau đó sẽ gọi ngoại lệ.

dữ liệu chưa được khởi tạo tuyên bố tĩnh sẽ đi vào phân khúc BSS để tiết kiệm không gian trong tập tin thực thi. Khu vực này được cấp phát bởi bộ nhớ. dữ liệu khởi tuyên bố tĩnh sẽ đi vào phân khúc DỮ LIỆU, được đọc-ghi.