2009-10-12 30 views
18

Khi lập trình bằng ngôn ngữ C giống như kiểu số nguyên "mặc định" của một người là int hoặc uint/unsigned int? Theo mặc định, tôi có nghĩa là khi bạn không cần số âm nhưng một trong hai nên dễ dàng đủ lớn cho dữ liệu bạn đang nắm giữ. Tôi có thể nghĩ ra những lý lẽ tốt cho cả hai:Loại int mặc định: Đã ký hoặc Chưa ký?

đã ký: Hành vi tốt hơn về mặt toán học, ít khả năng xảy ra hành vi lạ nếu bạn cố gắng xuống dưới 0 trong một số trường hợp ranh giới mà bạn không nghĩ đến, thường tránh trường hợp góc lẻ tốt hơn.

unsigned: Cung cấp thêm một chút bảo đảm chống tràn, chỉ trong trường hợp giả định của bạn về các giá trị là sai. Phục vụ dưới dạng tài liệu mà giá trị được biểu thị bằng biến nên không bao giờ là là số âm.

Trả lời

13

Các Google C++ Style Guide có một ý kiến ​​thú vị về số nguyên unsigned:

(quote sau :)

On Unsigned Số nguyên

Một số người, trong đó có một số tác giả sách giáo khoa, đề nghị sử dụng các loại unsigned để đại diện cho những con số không bao giờ tiêu cực. Điều này được dự định như một hình thức tự tài liệu. Tuy nhiên, trong C, những lợi thế của tài liệu này là lớn hơn bởi các lỗi thực sự mà nó có thể giới thiệu. Hãy xem xét:

for (unsigned int i = foo.Length()-1; i >= 0; --i) ... 

Mã này sẽ không bao giờ chấm dứt! Đôi khi gcc sẽ nhận thấy lỗi này và cảnh báo bạn, nhưng thường thì nó sẽ không xảy ra. Các lỗi tương tự có thể xảy ra khi so sánh các biến đã ký và chưa ký. Về cơ bản, chương trình khuyến mãi loại C gây ra các loại unsigned để hành xử khác với một người có thể mong đợi.

Vì vậy, hãy ghi lại rằng biến là không âm khi sử dụng xác nhận. Không sử dụng một loại unsigned.

(trích dẫn kết thúc)

+6

Trên thực tế, tôi nghĩ rằng chương trình khuyến mãi loại C khiến * ký * ints hoạt động khác với một người có thể mong đợi. Unsigned ints hoạt động tốt, nếu bạn biết số học modulo, trong khi int đã ký có hành vi phụ thuộc vào triển khai thực hiện và chuyển đổi buồn cười khắp nơi. Nhưng nếu bạn chỉ sử dụng một, để tránh trộn chúng, nó sẽ phải được ký kết. Vì vậy, tôi đồng ý với kết luận rằng int unsigned không nên được sử dụng willy-nilly, nhưng thực sự tôi nghĩ rằng vòng xuống không nên được sử dụng willy-nilly hoặc ... –

+2

Nó đã được một thời gian rất dài kể từ khi GCC không thể cảnh báo rằng 'unsigned> = 0' như thường lệ. Hướng dẫn của Google là gây hiểu nhầm ở mức tốt nhất, nguy hiểm nhất, vì một kiểu rất phổ biến và rất chính xác cho một vòng lặp lặp sẽ là loại không dấu 'size_t'. Kiểm tra chính xác cho dòng chảy chưa được ký khi đếm lùi bằng bộ đếm gốc không là 'i! = ~ 0U'. –

3

tôi có xu hướng để đi với chữ ký, trừ khi tôi biết tôi cần unsigned, như int thường ký kết, và phải mất nhiều công sức để gõ unsigned int, và uint có thể gây ra lập trình viên khác tạm dừng nhẹ để suy nghĩ về những gì các giá trị có thể .

Vì vậy, tôi không thấy bất kỳ lợi ích nào để chỉ mặc định cho một unsigned, vì int bình thường được ký.

+2

+1 Tôi sẽ nói rõ hơn rằng: hầu hết các kỳ vọng của người lập trình (đặc biệt là nếu đến từ Java) là 'int' được ký theo mặc định. Nó sẽ là lạ để xem 'int' trong mã và cho nó để hiển thị hành vi unsigned. –

11

Chắc chắn đã ký. Nếu tràn lo lắng bạn, dòng chảy sẽ lo lắng cho bạn nhiều hơn, bởi vì đi "dưới số không" do tai nạn là dễ dàng hơn hơn int-max.

"unsigned" phải là lựa chọn có ý thức khiến nhà phát triển phải suy nghĩ về các rủi ro tiềm ẩn, chỉ sử dụng ở nơi bạn hoàn toàn chắc chắn không bao giờ bị tiêu cực (thậm chí không vô tình) và bạn cần không gian giá trị bổ sung .

+0

+1, cảm ơn, chỉ cần hỏi cùng một câu hỏi. Bit này là móc sắt cho tôi: "... rằng bạn cần không gian giá trị bổ sung." –

0

Tôi nghi ngờ có một câu trả lời thực sự tốt về ngôn ngữ cho điều này. Có đủ sự khác biệt giữa các ngôn ngữ và cách chúng xử lý các loại hỗn hợp mà không ai trả lời sẽ có ý nghĩa đối với tất cả (hoặc thậm chí nhiều nhất).

Trong các ngôn ngữ tôi sử dụng thường xuyên nhất, tôi sử dụng chữ ký trừ khi tôi có lý do cụ thể để làm khác. Đó là chủ yếu là C và C + + mặc dù. Trong một ngôn ngữ khác, tôi cũng có thể đưa ra một câu trả lời khác.

2

Bạn không nhận được nhiều 'bảo đảm chống tràn' với chưa ký. Bạn có khả năng nhận được hành vi khác lạ nhưng lạ lùng hơn với ký kết, nhưng hơi muộn hơn ... Tốt hơn để có được những giả định đó ngay trước khi có thể?

+0

Trong C, tràn không dấu được xác định; tràn đăng nhập là * undefined *. Đó là "bảo đảm chống lại tràn" với tôi. –

1

Cho phép gán kiểu cụ thể hơn (như int chưa ký) truyền tải thêm thông tin về cách sử dụng biến và có thể giúp trình biên dịch theo dõi bất kỳ lúc nào khi bạn chỉ định giá trị "không chính xác". Ví dụ, nếu bạn đang sử dụng một biến để theo dõi ID cơ sở dữ liệu của một đối tượng/phần tử, có (có thể) không bao giờ nên là một thời gian khi ID nhỏ hơn 0 (hoặc một); trong trường hợp này, thay vì khẳng định trạng thái đó, sử dụng một giá trị số nguyên không dấu chuyển tải câu lệnh đó tới các nhà phát triển khác cũng như trình biên dịch.

4

Như quy tắc chung của ngón tay cái, tôi đã sử dụng int không dấu để đếm mọi thứ và ký số int để đo lường mọi thứ.

Nếu bạn thấy mình giảm hoặc trừ từ một dấu int, thì bạn phải ở trong ngữ cảnh mà bạn mong đợi cẩn thận không bị tràn (ví dụ, vì bạn đang ở một số bước mã cấp thấp trở lại từ cuối của một chuỗi, do đó, tất nhiên bạn đã đảm bảo rằng chuỗi đầu tiên đủ dài để hỗ trợ điều này). Nếu bạn không ở trong một bối cảnh như vậy, điều tuyệt đối quan trọng là bạn không đi dưới mức 0, thì bạn nên sử dụng một giá trị đã ký. Trong sử dụng của tôi, int không dấu là giá trị hoàn toàn không thể âm (hoặc cho một trong một triệu tình huống mà bạn thực sự muốn modulo 2^N số học), không cho giá trị mà chỉ xảy ra không tiêu cực, trong thực hiện hiện tại, có thể.

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