2010-02-14 41 views
5

Các ký tự không khớp đã ký/không dấu có nhất thiết không?C89: ký hiệu/không khớp không khớp

Đây là chương trình của tôi:

int main(int argc, char *argv[]) { 
    unsigned int i; 

    for (i = 1; i < argc; i++) { // signed/unsigned mismatch here 

    } 
} 

argc được ký kết, i thì không. Đây co phải vân đê?

+0

Không hoàn toàn là lừa đảo, nhưng đáng đọc: http://stackoverflow.com/questions/859943/c-how-can-i-fix-warnings-like-comparison-between-signed-and-unsigned – finnw

Trả lời

9

"các ký tự không khớp/đã ký" có thể không hợp lệ. Trong câu hỏi của bạn, bạn đang hỏi về sự so sánh. Khi so sánh hai giá trị của cùng một loại cơ sở, nhưng một giá trị đã ký và một dấu chưa ký, giá trị đã ký được chuyển thành unsigned. Vì vậy,

int i = -1; 
unsigned int j = 10; 

if (i < j) 
    printf("1\n"); 
else 
    printf("2\n"); 

in 2, chứ không phải 1. Điều này là do trong i < j, i được chuyển đổi thành một unsigned int. (unsigned int)-1 bằng UINT_MAX, một số rất lớn. Do đó, điều kiện đánh giá là sai và bạn nhận được mệnh đề else.

Ví dụ cụ thể của bạn, argc được đảm bảo là không âm, vì vậy bạn không phải lo lắng về "không khớp".

+0

lý do tại sao đã ký chuyển đổi thành unsigned (tại sao không ngược lại)? hành vi này được chuẩn hóa? – triclosan

+0

@triclosan, vâng. Các quy tắc hơi phức tạp, nhưng đối với 'int' và' unsigned int', vì chúng có cùng thứ hạng, kiểu đã ký được chuyển thành kiểu unsigned. Xem phần 6.3.1.8 của N1256 để biết chi tiết. –

1

Nó không phải là một vấn đề thực sự trong trường hợp cụ thể của bạn, nhưng trình biên dịch không thể biết rằng argc sẽ luôn luôn có giá trị mà sẽ không gây ra bất kỳ vấn đề.

+0

Nếu 'argc' quá lớn để vừa với' int', bạn có vấn đề nghiêm trọng :-) – finnw

+0

Không nhất thiết. 'INT_MAX' có thể thấp đến 32767 và tôi đã thấy các dòng lệnh vượt quá vài trăm kilobyte. Tiện ích xargs (1) được biết là đạt tới giới hạn đó một cách dễ dàng. – Jens

1

Nó chỉ là gián tiếp một vấn đề.

Những điều xấu có thể xảy ra nếu bạn sử dụng số nguyên đã ký cho các hoạt động bitwise như &, |, <<>>.
điều xấu hoàn toàn khác nhau có thể xảy ra nếu bạn sử dụng số nguyên unsigned cho số học (underflow, vòng lặp vô hạn khi kiểm tra nếu một số là >= 0 vv)

Bởi vì điều này, một số trình biên dịch và các công cụ kiểm tra tĩnh sẽ phát đi cảnh báo khi bạn kết hợp các số nguyên đã ký và chưa ký trong một trong hai loại thao tác (thao tác số học hoặc bit).

Mặc dù nó có thể an toàn để trộn chúng trong các trường hợp đơn giản như ví dụ của bạn, nếu bạn làm điều đó có nghĩa là bạn không thể sử dụng các công cụ kiểm tra tĩnh đó (hoặc phải vô hiệu hóa các cảnh báo đó có thể có nghĩa là các lỗi khác không bị phát hiện.

Đôi khi bạn không có lựa chọn, ví dụ: khi thực hiện số học về các giá trị loại size_t trong mã quản lý bộ nhớ.

Trong ví dụ của bạn, tôi sẽ dính vào int, chỉ vì đơn giản hơn để có ít loại hơn và int sẽ ở trong đó vì đó là loại đối số đầu tiên là main().

1

Không tệ. Tôi muốn sửa chữa cảnh báo trình biên dịch liên quan đến ký/không khớp không khớp vì những điều xấu có thể xảy ra ngay cả khi chúng không có hoặc không thể. Khi bạn phải sửa một lỗi vì sự không khớp đã ký/unsigned, trình biên dịch về cơ bản là nói "Tôi đã nói với bạn như vậy". Đừng bỏ qua cảnh báo của nó ở đó vì một lý do.

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