2013-07-22 34 views
6

tôi có mã này:C Strings So sánh với Equal Đăng

char *name = "George" 

if(name == "George") 
    printf("It's George") 

Tôi nghĩ rằng chuỗi c không thể được so sánh với == dấu hiệu và tôi phải sử dụng strcmp. Vì lý do không rõ khi tôi biên dịch với gcc (phiên bản 4.7.3), mã này hoạt động. Tôi mặc dù điều này là sai bởi vì nó giống như so sánh con trỏ vì vậy tôi tìm kiếm trong google và nhiều người nói rằng nó sai và so sánh với == không thể được thực hiện. Vậy tại sao phương pháp so sánh này hoạt động?

+6

sử dụng 'strcmp()', bạn đang so sánh địa chỉ. –

+0

Bạn có thể kiểm tra xem tại đây http://stackoverflow.com/questions/13253113/strcmp-with-pointers-not-working-in-c. – someone

+1

@nouney UB là gì? Tôi không thấy lý do nào cho nó. –

Trả lời

27

Tôi nghĩ rằng chuỗi c không thể được so sánh với dấu == và tôi phải sử dụng strcmp

Đúng vậy.

tôi dù rằng đây là sai vì nó cũng giống như so sánh con trỏ vì vậy tôi đã tìm kiếm trong google và nhiều người nói rằng đó là sai lầm và so sánh với == không thể được thực hiện

Đúng quá.

Vậy tại sao phương pháp so sánh này hoạt động?

Nó không "hoạt động". Chỉ có dường như hoạt động.

Lý do tại sao điều này xảy ra có thể là tối ưu hóa trình biên dịch: hai chuỗi ký tự giống hệt nhau, do đó trình biên dịch thực sự chỉ tạo một phiên bản của chúng và sử dụng cùng một con trỏ/mảng đó bất cứ khi nào chuỗi được tham chiếu.

1

Điều này sẽ không thành công, vì bạn đang so sánh hai con trỏ khác nhau của hai chuỗi riêng biệt. Nếu mã này vẫn hoạt động, thì đây là kết quả của việc tối ưu hóa nặng GCC, chỉ giữ một bản sao để tối ưu hóa kích thước.

Sử dụng strcmp(). Link.

+2

OP chỉ tuyên bố rằng các chuỗi được bật bằng nhau. Ông cũng biết tại sao 'strcmp()' nên được sử dụng. Đây không phải là câu trả lời. Nó cũng sai, bởi vì "bạn đang so sánh hai con trỏ khác nhau của hai chuỗi riêng biệt" là không đúng - vì chính lý do tôi giải thích trong câu trả lời của tôi. –

+0

Chuỗi bằng nhau, nhưng chúng được đặt ở hai vị trí bộ nhớ khác nhau. Kết quả là con trỏ của chúng khác nhau và so sánh là sai. Nếu mã này vẫn hoạt động, thì đây là kết quả của việc tối ưu hóa nghiêm trọng GCC. –

+0

"nhưng chúng được đặt ở hai vị trí bộ nhớ khác nhau" - không, chúng không, tôi đề nghị bạn cuối cùng ** đọc ** câu trả lời của tôi. –

4

So sánh bạn đã so sánh với vị trí vị trí của hai chuỗi, thay vì nội dung của chúng. Nó chỉ xảy ra khi trình biên dịch của bạn quyết định chỉ tạo ra một chuỗi ký tự chứa các ký tự "George". Điều này có nghĩa là vị trí của chuỗi được lưu trữ trong name và vị trí của số thứ hai "George" giống nhau, do đó so sánh trả về khác 0.

Trình biên dịch không bắt buộc phải làm điều này, tuy nhiên có thể dễ dàng tạo hai chuỗi ký tự khác nhau, với các vị trí khác nhau nhưng cùng nội dung và so sánh sẽ trả về 0.

8

Chỉ cần để cung cấp một tài liệu tham khảo để trả lời @ H2CO3 của:

C11 6.4.5 Chuỗi literals

Đó là không xác định liệu những mảng là khác biệt cung cấp các yếu tố của họ có giá trị thích hợp. Nếu chương trình tìm cách sửa đổi một mảng như vậy, hành vi là không xác định.

Điều này có nghĩa rằng trong ví dụ của bạn, name (một chuỗi chữ "George") và "George" có thể và không thể chia sẻ cùng một vị trí, nó tùy thuộc vào việc thực hiện. Vì vậy, không tính vào điều này, nó có thể kết quả khác nhau trong các máy khác.

+3

Điều này thực sự hữu ích, +1. –

+0

+1, GCC sẽ đặt tất cả các chuỗi ký tự trong phần .rodata và đủ thông minh để loại bỏ trùng lặp. :) – ludesign

0

Nếu bạn so sánh hai đoạn bạn đang so sánh các địa chỉ cơ sở của các chuỗi đó không phải là các ký tự thực trong các chuỗi đó. để so sánh các chuỗi, hãy sử dụng các hàm thư viện strcmp()strcasecmp() hoặc viết chương trình như thế này. dưới đây không phải là một mã đầy đủ chỉ cần logic để so sánh chuỗi.

void mystrcmp(const char *source,char *dest) 
{ 
    for(i=0;source[i] != '\0';i++) 
     dest[i] = source[i]; 
    dest[i] = 0; 

}