2015-10-16 37 views
28

Nếu tôi tuyên bố và sử dụng một con trỏ như thế này:Tại sao tôi có thể sử dụng con trỏ làm chuỗi khi được khai báo với dấu ngoặc kép, nhưng không phải dấu ngoặc nhọn, trong C?

int counter; 
char *pCow = "pCow goes MOO"; 

for(counter = 0; counter < 14; counter++) 
    printf("%c", pCow[counter]); 

nó sẽ hiển thị toàn bộ chuỗi và các công trình và vâng và có nhiều niềm vui.

Tuy nhiên, nếu tôi sử dụng một initializer như thế này:

int counter; 
char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 

for(counter = 0; counter < 14; counter++) 
    printf("%c", pCow[counter]); 

chương trình bị treo và pCow từ chối Moo cho niềm vui ăn chơi của tôi!

3 Warnings. 0 Errors 
line 11 (near initialization for 'pCow') [enabled by default] C/C++ Problem 
line 11 excess elements in scalar initializer [enabled by default] C/C++ Problem 
line 11 initialization makes pointer from integer without a cast [enabled by default] C/C++ Problem 

Yêu thích được thử nghiệm trong CDT Eclipse.

+3

Nếu đây là C (và không phải C++) thì 'char * pCow = (char []) {'p', 'C', 'o', 'w', '', 'g', 'o' , 'e', ​​'s', '', 'M', 'O', 'O', '\ 0'}; 'sẽ hoạt động và có cùng tác dụng. – immibis

+0

Lưu ý rằng giải pháp @immibis trên ↑ yêu cầu C99 trở lên. Tra cứu trên _Compound Literals_ để biết thêm về nó. –

+1

Có thể trùng lặp của [Chuỗi ký tự so với mảng char khi khởi tạo một con trỏ] (http://stackoverflow.com/questions/30533439/string-literals-vs-array-of-char-when-initializing-a-pointer) –

Trả lời

40

Trong trường hợp này, pCow được thiết lập để địa chỉ của một c-chuỗi trong bộ nhớ tĩnh:

char *pCow = "pCow goes MOO"; 

Trong trường hợp này, pCow được thiết lập với giá trị 'p' (ví dụ, 112):

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 

Vì địa chỉ 112 nhiều khả năng nhất vào bộ nhớ bị hạn chế/không hợp lệ, khiến chương trình của bạn phát nổ khi bạn truy cập pCow[counter].

"Cảnh báo " các phần tử dư thừa trong trình khởi tạo vô hướng " cho bạn biết rằng nó bỏ qua tất cả nội dung sau 'p' vì con trỏ chỉ cần một giá trị.

Cảnh báo "khởi tạo con trỏ từ số nguyên mà không có một dàn diễn viên" được thông báo rằng bạn đang sử dụng 'p' như một con trỏ, mà có lẽ không phải là một ý tưởng tốt ...

Những gì bạn muốn làm là tuyên bố pCow như một mảng nhân vật chứ không phải là một con trỏ nhân vật nếu bạn muốn sử dụng cú pháp initializer:

char pCow[] = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 
+0

Có ý nghĩa. Cảm ơn! Bạn thật nóng bỏng. : | (không thể chấp nhận như câu trả lời nhưng tho. nút sẽ không nhấp. Ill lấy lại cho nó!) –

+2

@JawiMmm - Vâng, [họ làm điều đó có mục đích] (http://meta.stackexchange.com/questions/50697/time-limit-on-accepting-an-answer). Trong mọi trường hợp, tôi vui vì điều này đã giúp bạn! Trên một lưu ý riêng biệt, [sử dụng một 'char *' để trỏ đến một chuỗi chữ c không phải là một ý tưởng hay, hoặc là] (http://stackoverflow.com/questions/16767042/deprecated-conversion-from-string-constant -to-char-in-c? lq = 1) (bạn nên sử dụng 'const char *' thay thế). – DaoWen

+0

Lưu ý sự khác biệt ở đây: sử dụng 'char []' tạo mảng dưới dạng biến cục bộ và sao chép dữ liệu tĩnh vào, trong khi 'char *' chỉ tạo một con trỏ làm biến cục bộ, sau đó có thể trỏ đến dữ liệu tĩnh mà không sao chép bất kỳ thứ gì (đó là lý do tại sao bạn muốn 'const char *' trỏ đến các chuỗi ký tự chuỗi). – hyde

11

"pCow goes MOO" là một chuỗi l lặp lại và có hai cách sử dụng khác nhau. Hoặc bạn có thể sử dụng nó làm công cụ khởi tạo cho một mảng:

char aCow[] = "pCow goes MOO"; 

Trong trường hợp đó nội dung của chuỗi ký tự được sao chép vào mảng.

Hoặc cách khác, bạn có thể sử dụng chuỗi ký tự dưới dạng mảng liên tục độc lập ở bất kỳ đâu trong chương trình của bạn. Ví dụ: . Vì vậy, có sự khác biệt đặc biệt giữa hai loại này:

char aCow[] = "pCow goes MOO"; 
char* pCow = "pCow goes MOO"; 

Trong trường hợp đầu tiên, chữ được sao chép vào mảng. Trong trường hợp thứ hai, chữ vẫn là một hằng số độc lập trong bộ nhớ chỉ đọc, mà chúng ta trỏ đến bằng một con trỏ. Cái cũ có thể được sửa đổi, cái sau không thể.

Đối với trường hợp của

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; 

Bạn đang sử dụng một con trỏ, nhưng bạn không có chuỗi chữ. Thay vào đó bạn có một danh sách khởi tạo dành cho một mảng. Một trình biên dịch tốt sẽ cảnh báo bạn về "initializer dư thừa". Lý do mà việc biên dịch mã là một quy tắc rất kỳ lạ trong C, cho phép các biến đơn giản được khởi tạo với các dấu ngoặc, ví dụ: int x = {1};. Vì vậy, trình biên dịch sử dụng quy tắc này để khởi tạo con trỏ trỏ đến địa chỉ 'p', điều này tất nhiên là vô nghĩa, và sau đó nó loại bỏ phần còn lại của danh sách khởi tạo.

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