2012-05-24 26 views
5

Vì vậy, tôi đã làm các xét nghiệm sau:Chuỗi ký tự chứa ' 0' - tại sao chúng không giống nhau?

char* a = "test"; 
char* b = "test"; 
char* c = "test\0"; 

Và bây giờ các câu hỏi:

1) Có đảm bảo rằng a==b? Tôi biết tôi đang so sánh địa chỉ. Điều này không có nghĩa là so sánh các chuỗi, nhưng liệu các chuỗi ký tự giống hệt nhau có được lưu trữ ở một vị trí bộ nhớ duy nhất hay không

2) Tại sao không a==c? Không nên trình biên dịch có thể thấy rằng họ đang đề cập đến cùng một chuỗi?

3) Có thêm \0 được thêm vào cuối c, ngay cả khi nó đã có sẵn không?

Tôi không muốn hỏi 3 câu hỏi khác nhau vì điều này dường như có liên quan, xin lỗi 'bout.

Lưu ý: Thẻ đúng, tôi quan tâm đến C++. (mặc dù vui lòng nêu rõ nếu hành vi khác với C)

+7

Phải là 'char const * a = ...'. –

+0

a và b có cùng giá trị, nhưng điều đó không nhất thiết có nghĩa là chúng là chuỗi _same_. –

+0

@HunterMcMillen - thực sự đó chính là ý nghĩa của nó. –

Trả lời

18

Có bảo đảm rằng a == b không?

số Nhưng nó được cho phép bởi §2.14.5/12:

Cho dù tất cả xâu là riêng biệt (có nghĩa là, được lưu trữ trong đối tượng không chồng lấn) là thực hiện xác định. Hiệu quả của việc cố gắng sửa đổi một chuỗi ký tự là không xác định.

Và như bạn có thể nhìn thấy từ đó câu cuối cùng sử dụng char* thay vì char const* là một công thức cho các rắc rối (và trình biên dịch của bạn nên được bác bỏ nó; đảm bảo bạn có các cảnh báo được kích hoạt và mức độ phù hợp cao được chọn).

Tại sao không phải là == c? Không nên trình biên dịch có thể thấy rằng họ đang đề cập đến cùng một chuỗi?

Không, chúng không bắt buộc phải đề cập đến cùng một mảng ký tự. Một có năm yếu tố, sáu yếu tố còn lại. Việc triển khai có thể lưu trữ hai trong bộ nhớ chồng chéo, nhưng điều đó không bắt buộc.

Có thêm \ 0 được thêm vào cuối c, ngay cả khi nó đã có sẵn không?

Có.

+0

Cũng có thể đáng giải thích rằng '' test "' là một 'char const [5]' trong bối cảnh tại sao A & B * có thể * trùng lặp nhưng C sẽ không. – AJG85

+0

Cảm ơn. Một câu hỏi nữa. Nếu tôi sử dụng 'strcmp' để so sánh' a' và 'c', nó sẽ nói chúng bằng nhau? Ngoài ra, nó được cho phép đối với 'a == c'? – AMCoder

+0

@ AJG85 tại sao sẽ không 'c' chồng lên nhau? Tiêu chuẩn này cho phép rõ ràng nó (câu trích dẫn nằm trong câu trả lời và nó không giới hạn các chữ giống hệt nhau), và một chương trình không thể nói sự khác biệt mà không cần gọi hành vi không xác định. –

6

1 - hoàn toàn không. a == b có thể mặc dù nếu trình biên dịch chọn chia sẻ cùng một chuỗi tĩnh.

2 - vì chúng KHÔNG đề cập đến cùng một chuỗi

3 - có.

Hành vi không khác biệt giữa C và C++ ở đây ngoại trừ trình biên dịch C++ nên từ chối gán cho không phải char *.

+0

Chuỗi ký tự thành 'char *' không được dùng nữa, nhưng không bị cấm trong C++. –

+0

@james nó bị cấm trong C++ 11 –

+0

@ JohannesSchaub-litb: Không đời nào! Đó là tin tốt nhất mà tôi đã nghe cả ngày. g ++ 4.7, clang 3.1 và VC11 đều chấp nhận chuyển đổi, nhưng tôi mong đợi ngày mà chúng không :-) –

2

Vấn đề ở đây là bạn đang trộn các khái niệm về con trỏ và tương đương văn bản.

Khi bạn nói a == b hoặc a == c, bạn sẽ hỏi liệu con trỏ có liên quan đến cùng một địa chỉ thực hay không. Bài kiểm tra không liên quan gì đến nội dung văn bản của các con trỏ.

Để có được tương đương văn bản bạn nên sử dụng strcmp

+0

Lưu ý rằng 'strcmp' sẽ dừng tại * đầu tiên * không, vì vậy các chuỗi' a' và 'c' sẽ so sánh bằng nhau mặc dù một dài hơn giá trị kia. –

+0

@MarkRansom có ​​chiều dài tương đương theo nghĩa văn bản mặc dù đó là những gì strcmp sẽ xem xét. Có lẽ tôi nên mở rộng câu trả lời của tôi thành 3 cõi có thể quan trọng ở đây: tương đương con trỏ, tương đương văn bản và tương đương bộ nhớ – JaredPar

+0

-1 xin lỗi nhưng tôi có so sánh con trỏ ở đó vì tôi muốn so sánh con trỏ. Đó là những gì câu hỏi là về. – AMCoder

4

1) Có phải đảm bảo rằng a == b?

Nó không phải. Lưu ý rằng bạn đang so sánh các địa chỉ và chúng có thể trỏ đến các vị trí khác nhau. Hầu hết các trình biên dịch thông minh sẽ gấp lặp lại hằng số này, vì vậy các con trỏ có thể so sánh bằng nhau, nhưng lại không được đảm bảo bởi tiêu chuẩn.

2) Tại sao không == c? Không nên trình biên dịch có thể thấy rằng họ đang đề cập đến cùng một chuỗi?

Bạn đang cố gắng so sánh con trỏ, chúng trỏ đến các vị trí bộ nhớ khác nhau. Ngay cả khi bạn so sánh nội dung của các con trỏ như vậy, chúng vẫn không bằng nhau (xem câu hỏi tiếp theo).

3) Có thêm \ 0 được thêm vào cuối c, ngay cả khi nó đã có chứa?

Có, có.

+0

Tôi biết tôi đang so sánh các địa chỉ, hãy đặt câu hỏi. Để xóa câu hỏi - là các chuỗi ký tự giống hệt nhau nằm trong cùng một bộ nhớ? – AMCoder

+0

Tôi đoán các con trỏ cho 'a' và' c' có thể bằng nhau. Một chương trình không thể nói sự khác biệt mà không cần gọi UB. –

+0

@R. Martinho Fernandes: Đó là một điểm tốt, tôi tin rằng bạn là đúng. –

0

Nếu bạn đang so sánh con trỏ so với a! = B, b! = C và c! = A. Trừ khi trình biên dịch đủ thông minh để nhận thấy rằng hai chuỗi đầu tiên của bạn giống nhau.

Nếu bạn làm một strcmp (str, str) thì tất cả các chuỗi của bạn sẽ trở lại dưới dạng kết quả phù hợp.

Tôi không chắc liệu trình biên dịch có thêm một kết thúc null bổ sung vào c hay không, nhưng tôi đoán là nó sẽ như thế.

3

Lưu ý đầu tiên rằng điều này phải là const char * vì đó là những gì chuỗi ký tự phân rã thành.

  1. Cả hai tạo mảng được khởi tạo bằng 't' 'e' 't' folowed bởi '\ 0' (length = 5). So sánh bình đẳng sẽ chỉ cho bạn biết nếu cả hai đều bắt đầu với cùng một con trỏ, không phải nếu chúng có cùng nội dung (mặc dù một cách hợp lý, hai ý tưởng theo nhau).
  2. A không bằng C vì các quy tắc tương tự áp dụng, a = 't' 'e' 's' 't' '\ 0' và b = 't' 'e' 's' 't' ' \ 0 '' \ 0 '
  3. Có, trình biên dịch luôn thực hiện nó và bạn không nên làm gì nếu bạn đang tạo chuỗi như thế này. Tuy nhiên, nếu bạn đã gộp một mảng và tự điền nó, bạn cần đảm bảo bạn thêm \ 0.

Lưu ý rằng đối với # 3 của tôi, const char [] = "Hello World" cũng sẽ tự động nhận \ 0 ở cuối, tôi đã refferring để tự điền mảng, không có trình biên dịch làm việc nó ra.

+0

Tôi không nghĩ rằng 'a' và' c' được đảm bảo bất bình đẳng. Tiêu chuẩn cho phép thực hiện lưu trữ các chữ trong bộ nhớ chồng chéo, và các chương trình không thể cho biết sự khác biệt mà không cần gọi UB. –

+0

Tôi thực sự đồng ý với bạn đã kiểm tra điều đó, đó là một điểm xen kẽ mà tôi chưa từng nghe. Điểm của tôi vẫn sẽ là trình biên dịch chắc chắn sẽ đặt hai terminator null trong trường hợp 2 mặc dù mà làm cho các hoạt động bất bình đẳng, ngay cả khi đọc các chuỗi & kiểm tra con trỏ của họ sẽ được bình đẳng. Ngoài ra, nếu bạn ghi lại độ dài của chuỗi mà bạn đã tạo cho c, bạn có thể đọc qua strlen() 1 và bạn không thể cho (trừ khi chúng ở cùng vị trí như bạn đã nói, nhưng bạn sẽ không thể Tôi có thể đảm bảo điều đó). –

+0

* Ngay cả khi trình biên dịch lưu trữ chúng trong cùng một vị trí *, 'a [5]' (cố gắng đọc giá trị tại cùng một vị trí như 'c [5]') sẽ gọi hành vi không xác định, vì 'a' trỏ tới một mảng kích thước 5. Nó không quan trọng rằng có xảy ra là một mảng nằm xung quanh trong cùng một vị trí. –

0

Như đã nói một vài lần trong các câu trả lời khác, bạn đang so sánh con trỏ.Tuy nhiên, tôi sẽ thêm rằng strcmp(b,c) phải đúng, vì nó dừng kiểm tra tại \0 đầu tiên.

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