2010-09-03 32 views

Trả lời

7

Chuẩn quy định rằng chuỗi ký tự được xác định const. Bạn không thể thay đổi nó.

Trình biên dịch đặt chữ vào phần bộ nhớ chỉ đọc. Bạn có thể đầu ra lắp ráp và quan sát điều này. Nếu bạn đang sử dụng GCC nó được thực hiện thông qua cờ -s. Nó sẽ đặt chuỗi trong một phần .rodata.

+0

và nếu tôi viết char arr [10] = "nyks"; arr [2] = 'p'; nó sẽ hiển thị lỗi seg một lần nữa? – Kraken

+1

@hopeful, no. Điều đó là tốt, vì bạn đang phân bổ một mảng (có thể sửa đổi) trên ngăn xếp. Như tôi đã nói ở trên, bạn có thể bỏ kích thước để C tính toán nó. –

+1

Không, trong C, chuỗi ký tự không có loại 'const'. Tuy nhiên, đó là hành vi không xác định để viết cho họ. –

15

Hành vi không xác định là cố ghi đè một chuỗi ký tự. C99 §6.4.5/6:

Nếu chương trình tìm cách sửa đổi một mảng, hành vi này không được xác định.

Điều này được ghi lại trong Phụ lục J.2 (hành vi chưa xác định).

Nếu bạn thay vì làm:

char p[] = "nyks"; 

bạn có thể phân bổ và khởi tạo một tự động (stack) mảng nhân vật. Trong trường hợp đó, nó là hoàn toàn tốt đẹp để sửa đổi các yếu tố.

+0

+ nó không được phép có khai báo chuỗi không liên tục bằng chữ nữa. GCC sẽ đưa ra một cảnh báo lớn màu đỏ. –

+0

+1 để tham chiếu đến thông số – linuxuser27

0

literals chuỗi là không thể thay đổi được ... Khả năng viết char *p="nyks"; thực sự là một lỗ loại hệ thống trong C.

+0

Lỗ hổng hệ thống kiểu này như thế nào? – alternative

+0

Vì lý do lịch sử, trình biên dịch được phép âm thầm bỏ đi 'const' trong trường hợp này. Tất nhiên, tại thời điểm 'const' được phát minh và họ nhận thấy rằng một hằng số chuỗi phải có hiệu quả là' const char * ', nó có thể được coi là một sự thay đổi lớn để cấm gán' char * '. – RBerteig

+0

@mathepic Nó là từ quan điểm của C++, ít nhất. Trong C++, ký tự chữ là loại const char [N]. Một chuỗi ký tự có thể được chuyển đổi hoàn toàn thành char không * const (loại bỏ trình độ const mà không có một diễn viên). Đây là một lỗ hệ thống kiểu trong C++, nhưng hành vi này được thừa kế từ C. Đây là một tính năng không được chấp nhận trong C++, và sẽ bị loại bỏ hoàn toàn trong C++ 0x. Đây là những gì tiêu chuẩn C phải nói về vấn đề của câu hỏi này: "Nếu chương trình cố gắng sửa đổi một mảng như vậy, hành vi đó là không xác định." trong đó 'mảng như vậy' là một mảng ký tự chứa một chuỗi ký tự. – usta

1

Đó dịch để (chủ yếu):

#include<stdio.h> 
const char privatestring[5] = {"nyks"}; 

void main() 
{ 
    char *p = const_cast<char*>(privatestring); 
    p[2]='n';   

    printf("%s",p);   
}   

Trình biên dịch được phép đặt privatestring ở nơi nào đó mà bạn chỉ có quyền truy cập đọc. Nó làm const_cast cho tương thích ngược với các chương trình được viết trước đó là một từ khóa const.

3

Các câu trả lời khác cho biết chế độ xem từ góc độ tiêu chuẩn, nhưng đây là lý do tại sao sự cố bị lỗi.

Trình biên dịch thường đặt các chương trình literals - đặc biệt là các chuỗi - trong bộ nhớ chỉ đọc. Bộ nhớ được đánh dấu chỉ đọc bởi hệ điều hành, vì vậy bất kỳ nỗ lực để ghi vào nó sẽ bị mắc kẹt và, trên nền tảng của bạn, đây là những gì lỗi phân đoạn chỉ ra; một nỗ lực để thực hiện một thao tác trên một số bộ nhớ không được phép. Loại tai nạn khác liên quan đến việc sử dụng bộ nhớ kém là lỗi bus, thường cho biết truy cập bộ nhớ không liên kết hoặc ghi vào một trang không được ánh xạ. Đối với mã C, sự khác biệt gần như hoàn toàn là học tập (một số cách triển khai ngôn ngữ khác sử dụng những lỗi này để giúp họ quản lý bộ nhớ).

Lưu ý rằng việc bẫy ghi vào chỉ đọc là độc lập với ngữ nghĩa chính thức của ngôn ngữ. Trong khi bạn có thể có một char* trỏ đến nó, bạn vẫn không thể viết nó. Luôn luôn xử lý các chương trình literals như thể họ đang trỏ đến bộ nhớ liên tục và bạn sẽ không đi sai (rằng họ không phải là theo mặc định là vì sự cần thiết phải hỗ trợ khả năng tương thích với các chương trình cũ).

+0

Và tiêu chuẩn (C89) không xác định điều gì sẽ xảy ra khi bạn viết chính xác theo nghĩa đen bởi vì họ không muốn chỉ định chính xác cách xảy ra sự cố và vì họ cũng muốn cho phép trình biên dịch hỗ trợ chuỗi có thể ghi họ muốn (ví dụ, thông qua một chuyển đổi; gcc có '-fwritable-strings' để làm điều đó, mặc dù cần đó thực sự chỉ là một dấu hiệu của một chương trình bị hỏng nặng nếu bạn hỏi tôi). –

1

Giá trị là chuỗi ký tự không thể sửa đổi được vì các chữ được lưu trữ trong bộ nhớ chỉ đọc, hãy thử p [] thay vào đó. Các lỗi thông thường xảy ra do sử dụng sai con trỏ.

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