2011-12-29 25 views
9

Ví dụ: tại sao int dài lại có công cụ sửa đổi chữ, nhưng int ngắn thì không? Tôi đang đề cập đến câu hỏi sau trên trang web này: C# compiler number literalsTại sao một số loại không có biến tố theo nghĩa đen

Nói chung, C# có vẻ là một ngôn ngữ được thiết kế và nhất quán rất tốt. Có lẽ có lý do chính đáng để cung cấp các công cụ sửa đổi chữ cho một số loại, nhưng không phải cho tất cả. Nó là gì?

+1

Hãy xem câu hỏi này (và câu trả lời của Eric Lippert): http://stackoverflow.com/questions/1678591/why-are-number-suffixes-necessary –

Trả lời

35

Tại sao int dài có công cụ sửa đổi chữ, nhưng ngắn int thì không?

Câu hỏi đặt ra là "tại sao C# không có tính năng này?" Câu trả lời cho câu hỏi đó luôn giống nhau. Các tính năng chưa được thực hiện theo mặc định; C# không có tính năng đó vì không có ai thiết kế, triển khai và vận chuyển tính năng này cho khách hàng.

Sự vắng mặt của đối tượng địa lý không cần biện minh. Thay vào đó, tất cả các tính năng phải được chứng minh bằng cách cho thấy rằng lợi ích của chúng vượt quá chi phí của chúng. Là người đề xuất tính năng này, onus là để bạn mô tả lý do tại sao bạn cho rằng tính năng này có giá trị; onus không phải là trên tôi để giải thích tại sao nó không phải là.

Có thể có lý do chính đáng để cung cấp công cụ sửa đổi chữ cho một số loại, nhưng không phải cho tất cả. Nó là gì?

Bây giờ, đó là một câu hỏi đáng trả lời hơn. Bây giờ câu hỏi đặt ra là "cái gì biện minh cho hậu tố theo chiều dài, và tại sao đó cũng không phải là lý do cho hậu tố tương tự về chữ viết tắt?"

Các số nguyên có thể được sử dụng cho nhiều mục đích khác nhau. Bạn có thể sử dụng chúng làm số học số. Bạn có thể sử dụng chúng làm bộ sưu tập cờ bit. Bạn có thể sử dụng chúng như các chỉ mục thành các mảng. Và có rất nhiều mục đích đặc biệt hơn. Nhưng tôi nghĩ rằng nó là công bằng để nói rằng hầu hết thời gian, số nguyên được sử dụng như số học số học.

Phần lớn các tính toán được thực hiện theo số nguyên bởi các chương trình bình thường bao gồm các số xa, nhỏ hơn nhiều so với dãy số nguyên 32 bit - khoảng +/- hai tỷ. Và rất nhiều phần cứng hiện đại là cực kỳ hiệu quả khi giao dịch chỉ với 32 bit số nguyên. Do đó, làm cho tinh thần để làm cho đại diện mặc định của các số được ký 32 bit số nguyên. Vì vậy, C# được thiết kế để thực hiện các phép tính liên quan đến các số nguyên được ký 32 bit trông hoàn toàn bình thường; khi bạn nói "x = x + 1" mà "1" được hiểu là một số nguyên 32 bit có dấu, và tỷ lệ cược là tốt mà x là quá, và kết quả của tổng là quá.

Điều gì sẽ xảy ra nếu tính toán không thể tách rời nhưng không vừa với phạm vi số nguyên 32 bit?các số nguyên 64 bit "dài" là một bước tiếp theo hợp lý; chúng cũng hiệu quả trên rất nhiều phần cứng và thời gian dài có một phạm vi đáp ứng nhu cầu của khá nhiều người không làm tổ hợp nhiệm vụ nặng có liên quan đến số lượng cực lớn. Do đó nó có ý nghĩa để có một số cách để xác định rõ ràng và chính xác trong mã nguồn mà chữ này ở đây được coi là một số nguyên dài.

Tình huống tương tác hoặc các tình huống trong đó các số nguyên được sử dụng làm trường bit, thường yêu cầu sử dụng các số nguyên không dấu. Một lần nữa, nó có ý nghĩa để có một cách rõ ràng và chính xác xác định rằng chữ này được dự định để được coi là một số nguyên không dấu.

Vì vậy, tổng hợp, khi bạn thấy "1", tỷ lệ cược là tốt mà phần lớn thời gian người dùng dự định sử dụng nó làm số nguyên có dấu 32 bit. Các trường hợp có khả năng nhất tiếp theo là người dùng dự định nó là một số nguyên dài hoặc một unsigned int hoặc unsigned long. Vì vậy, có những hậu tố ngắn gọn cho mỗi trường hợp đó.

Do đó, đối tượng địa lý được hợp lý hóa.

Tại sao đó không phải là biện minh cho quần short?

Vì trước tiên, trong mọi ngữ cảnh trong đó đoạn mã ngắn là hợp pháp, việc sử dụng chữ số nguyên là hợp pháp. "short x = 1;" hoàn toàn hợp pháp; trình biên dịch nhận ra rằng số nguyên phù hợp với một đoạn ngắn và cho phép bạn sử dụng nó.

Thứ hai, số học không bao giờ được thực hiện trong quần short trong C#. Số học có thể được thực hiện trong ints, uints, longs và ulongs, nhưng số học là không bao giờ thực hiện trong quần short. Quần short quảng bá cho int và số học được thực hiện trong ints, bởi vì như tôi đã nói trước đây, phần lớn các tính toán số học phù hợp với một int. Đại đa số làm không phải phù hợp với một đoạn ngắn. Số học ngắn có thể là chậm hơn trên phần cứng hiện đại được tối ưu hóa cho ints và số học ngắn không chiếm ít không gian hơn; nó sẽ được thực hiện trong ints hoặc longs trên chip.

Bạn muốn hậu tố "dài" cho trình biên dịch "số học này cần phải thực hiện trong thời gian dài" nhưng hậu tố "ngắn" không cho trình biên dịch biết "số học này cần được thực hiện trong quần short" không phải là một tính năng của ngôn ngữ C# để bắt đầu.

Lý do cung cấp hậu tố dài và cú pháp không dấu không áp dụng cho quần short. Nếu bạn cho rằng có lợi ích hấp dẫn đối với đối tượng địa lý, hãy nêu rõ lợi ích là gì. Không có lợi ích để biện minh cho chi phí của nó, tính năng này sẽ không được thực hiện trong C#.

+1

nhất quán phải là biện minh đủ mạnh, phải không? Tuy nhiên, sự mâu thuẫn này dường như ở đó vì một lý do: nó cảnh báo tôi về chi phí chuyển đổi thành int và ngược lại mỗi khi tôi cần làm bất cứ điều gì với ngắn hạn của tôi. –

+0

@Lund: Hầu như không có bất kỳ chi phí nào liên quan đến chuyển đổi, trừ khi sử dụng số học được kiểm tra. Số học được thực hiện trong sổ đăng ký CPU có kích thước tối thiểu 32 bit. Tải bộ nhớ và hướng dẫn lưu trữ actaully thực hiện chuyển đổi và chúng có thể thay đổi đôi chút trong số chu kỳ. Tuy nhiên, việc sử dụng bộ nhớ cache beter thường xuyên hơn là bù đắp cho bất kỳ tổn thất nào, có khả năng làm cho hiệu suất tổng thể sử dụng quần short tốt hơn so với sử dụng int. –

+3

@KevinCathcart: Tất nhiên là quần short được đóng gói chặt chẽ. Ví dụ, một chuỗi các quần short có thể khiến ít bộ nhớ cache bị thiếu hơn một mảng int. Nhưng thường tôi thấy những người khai báo * biến cục bộ * là ngắn vì họ cho rằng làm như vậy là "tiết kiệm hai byte bộ nhớ", điều đó là vô nghĩa. –

1

Nếu bạn khai báo một chữ ngắn và làm cho nó lớn hơn Short.MaxValue lỗi trình biên dịch sẽ xảy ra, nếu không chữ sẽ ngắn.

+1

Một chữ có thể dài, chẳng hạn như 1L. Rõ ràng không có thứ gì như một chữ ngắn. –

+1

@BasB: Điều này không hoàn toàn chính xác: bạn có thể khai báo một biến hoặc hằng số là 'short', nhưng bạn phải khởi tạo nó với một chữ không ngắn; việc kiểm tra phạm vi được thực hiện, như bạn lưu ý, bởi trình biên dịch. C# spec (4.0) định nghĩa các chữ trong phần 2.4.4, và, của các chữ số nguyên, nó nói rằng chúng "được sử dụng để viết các giá trị của các kiểu' int', 'uint',' long' và 'ulong'." – phoog

2

Từ một short có thể được ngầm chuyển đổi sang int, long, float, double, hoặc decimal; không cần phải sửa đổi theo nghĩa đen.

xem xét:

void method(int a) {} 
void method2() 
{ 
    short a = 4; 
    method(a); // no problems 
} 

Bạn có thể nhận thấy rằng charbyte cũng với từ bổ nghĩa đen, vì có thể vì lý do tương tự.

From To 
sbyte short, int, long, float, double, or decimal 
byte short, ushort, int, uint, long, ulong, float, double, or decimal 
short int, long, float, double, or decimal 
ushort int, uint, long, ulong, float, double, or decimal 
int  long, float, double, or decimal 
uint long, ulong, float, double, or decimal 
long float, double, or decimal 
char ushort, int, uint, long, ulong, float, double, or decimal 
float double 
ulong float, double, or decimal 
+4

Phương thức 2 của bạn đã chứng minh chuyển đổi 'short' =>' int', đó là hướng khác so với 'short s = 1; ' –

9

Theo MSDN:

short x = 32767; 

Trong tuyên bố trước đó, số nguyên đen 32767 là ngầm chuyển đổi từ int để ngắn. Nếu số nguyên nguyên không phù hợp với vị trí lưu trữ ngắn, lỗi biên dịch sẽ xuất hiện.

Vì vậy, đây là tính năng thời gian biên dịch. short không có hậu tố vì nó sẽ không bao giờ cần thiết.

Câu hỏi liên quan có thể là: Tại sao long, floatdecimal không có hậu tố?
Và một câu trả lời ngắn gọn là i + 1i + 1L có thể tạo ra các giá trị khác nhau và do đó có các loại khác nhau.

Nhưng không tồn tại những thứ như 'số học ngắn', giá trị short luôn được chuyển đổi thành int khi được sử dụng để tính toán.

+0

Henk, tôi thích viết của bạn. Đó là một sự xấu hổ tôi không thể chấp nhận hai câu trả lời. –

4

Như Eric đã chỉ ra trong nhận xét, câu trả lời của tôi dưới đây không có ý nghĩa. Tôi nghĩ rằng đó là chính xác hơn để nói rằng không có khả năng thể hiện một chữ ngắn trong C# và không có khả năng thể hiện một chữ ngắn trong IL chia sẻ một nguyên nhân phổ biến (thiếu một lý do thuyết phục cho tính năng này.) VB.Net dường như có một ngắn theo bất kỳ trường hợp nào, tôi đã để lại câu trả lời ở đây vì một số thông tin có thể thú vị, ngay cả khi lý do không chính xác.


Không có ngắn đen vì không có thực sự bất kỳ cách nào cho một đoạn ngắn đen được nạp trong IL, ngôn ngữ cơ bản được sử dụng bởi CLR. Điều này là do tất cả các loại 'ngắn' (bất kỳ thứ gì nhỏ hơn một int) được mở rộng hoàn toàn đến một int khi được nạp vào ngăn xếp hoạt động. Ký và unsigned tương tự như vậy là một vấn đề của hoạt động và không thực sự 'lưu trữ' với số hoạt động trên stack hoạt động.Các kiểu 'short' chỉ xuất hiện khi bạn muốn lưu trữ một số trên stack hoạt động vào một vị trí bộ nhớ, do đó, có các phép toán IL để chuyển đổi sang các loại 'ngắn' khác nhau (mặc dù nó vẫn thực sự mở rộng số trở lại một int sau khi chuyển đổi, nó chỉ đảm bảo rằng giá trị sẽ phù hợp để lưu trữ vào một trường của loại 'ngắn'.)

Các loại dài có một bộ định danh bằng chữ, mặt khác, do chúng là được xử lý khác nhau trên ngăn xếp hoạt động. Có một hướng dẫn Ldc_I8 riêng biệt để tải các giá trị dài không đổi. Ngoài ra còn có Ldc_R4 (do đó tại sao bạn cần 'f' cho float) và Ldc_R8 (C# chọn nó là mặc định nếu bạn sử dụng một số thập phân mà không có một specifier.) Decimal là một trường hợp đặc biệt, vì nó không thực sự là một kiểu nguyên thủy trong IL ; nó chỉ có một bộ định danh hằng số tích hợp 'm' trong C# để biên dịch thành một lời gọi hàm tạo. Đối với lý do tại sao không có các hoạt động ngắn đặc biệt (và các chữ ngắn tương ứng), có thể vì hầu hết các kiến ​​trúc CPU hiện tại không hoạt động với các thanh ghi nhỏ hơn 32 bit, do đó không có sự phân biệt ở mức CPU đáng để khai thác. Bạn có khả năng có thể tiết kiệm kích thước mã (về byte của IL) bằng cách cho phép 'tải ngắn' IL opcodes, nhưng với chi phí phức tạp thêm cho jitter; không gian mã được lưu có lẽ không đáng giá.

+0

("bạn có khả năng lưu kích thước mã ...") - Nhưng có * là "ngắn" opcodes, để lưu byte của IL (nghĩa là mã CIL ngắn, không nhất thiết là chúng liên quan đến kiểu dữ liệu 'ngắn'). Ví dụ, một thậm chí tồn tại đối với i4 (ints bốn byte): 'ldc.i4.s' lấy một đối số một byte và đẩy giá trị đó vào ngăn xếp dưới dạng int32. Từ spec: "Có các mã hóa ngắn đặc biệt cho các số nguyên –128 đến 127 (với mã hóa đặc biệt ngắn cho –1 đến 8)." – phoog

+4

Câu trả lời này không có ý nghĩa gì cả. Lỗi cơ bản là trong câu đầu tiên. Nếu lý do tại sao tính năng này không có trong C# là vì C# biên dịch thành IL, thì tại sao tính năng này lại bằng các ngôn ngữ khác biên dịch sang IL? –

0

Thời gian tôi đã "làm việc trong Ngắn" là các giá trị được lưu trữ trong Cơ sở dữ liệu.

Chúng là các giá trị số nguyên dương hiếm khi vượt quá 10 đến 20. (một byte hoặc sbyte đủ lớn, nhưng tôi nghĩ một chút sẽ khiến tôi không hối hận lựa chọn của mình, nếu mã được tái sử dụng trong một cách hơi khác)

Trường này được sử dụng để cho phép người dùng sắp xếp các bản ghi trong bảng. Bảng này cung cấp danh sách thả xuống hoặc nút radio được sắp xếp theo "thời gian" (bước một, bước hai, ...).

Làm quen với C# (và đủ tuổi để nhớ khi đếm byte là quan trọng), tôi nhận thấy nó sẽ hiệu quả hơn một chút. Tôi không làm toán trên các giá trị. Tôi chỉ Sắp xếp chúng (và trao đổi chúng giữa các bản ghi). Toán duy nhất cho đến nay là "MaxInUse" +1 (cho các bản ghi mới), đây là trường hợp đặc biệt "++ MaxInUse".Điều này là tốt, bởi vì thiếu một nghĩa đen "s = s + 2" sẽ phải là "s = (Int16) (s + 2)".

Bây giờ tôi thấy làm thế nào gây phiền nhiễu C# làm việc với các ints khác, tôi mong đợi để tham gia thế giới hiện đại và byte chất thải, JUST để làm cho trình biên dịch hạnh phúc.

Nhưng, không nên "làm cho trình biên dịch hài lòng" xếp hạng khoảng # 65 trong 10 mục tiêu lập trình hàng đầu của chúng tôi?

Có phải EVER là một lợi thế để trình biên dịch phàn nàn về việc thêm số nguyên "2" vào bất kỳ loại INTEGER nào không? Nó nên khiếu nại về "s = 123456", nhưng đó là một trường hợp khác.

Nếu có ai phải đối phó với toán học và quần short, tôi khuyên bạn nên tự tạo ra các chữ của riêng mình. (Có bao nhiêu bạn có thể cần?)

short s1= 1, s2 = 2, s123 = 123; 

Sau đó s = s + s2 chỉ gây phiền nhiễu một chút (và khó hiểu đối với những người theo dõi bạn).

+0

Có suy nghĩ, tôi nên kiểm tra, thay vì chỉ nổ ra một ý tưởng tốt. s = s + s2; Cung cấp cùng một lỗi như s = s + 2. Trình biên dịch C# rất khó chịu khi được gõ mạnh, Short + a Short mang lại giá trị Int. Điều này có thể là lý do tại sao một số người khẳng định rằng tất cả các toán học được thực hiện như Ints. Dựa trên thử nghiệm này, tôi đề xuất câu trả lời cho câu hỏi ban đầu. Một chữ ngắn không tồn tại, bởi vì nó sẽ không bao giờ hữu ích. Ngay cả khi bạn có một, bạn không thể thêm 2 Shorts và đặt nó vào Short khác. (Điều này dẫn tôi trở lại trong một vòng tròn để hỏi TẠI SAO. Nhưng, đó là cho một ngày khác.) –

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