Một đặc điểm thú vị của C so với một số ngôn ngữ khác là nhiều loại dữ liệu của nó dựa trên kích thước từ của kiến trúc đích, thay vì được chỉ định theo thuật ngữ tuyệt đối. Mặc dù điều này cho phép ngôn ngữ được sử dụng để viết mã trên các máy có thể gặp khó khăn với một số loại nhất định, nhưng điều này gây khó khăn cho việc thiết kế mã sẽ chạy ổn định trên các kiến trúc khác nhau. Hãy xem xét mã:
uint16_t ffff16 = 0xFFFF;
int64_t who_knows = ffff16 * ffff16;
Trên một kiến trúc có int
16 bit (vẫn đúng với nhiều bộ vi điều khiển nhỏ), mã này sẽ gán giá trị 1 bằng cách sử dụng hành vi được xác định rõ. Trên các máy có int
64 bit, nó sẽ gán giá trị 4294836225, một lần nữa sử dụng hành vi được xác định rõ. Trên các máy có int
32 bit, nó có thể sẽ gán giá trị -131071 (Tôi không biết đó sẽ là Hành vi được Xác định theo Thực hiện hay Không xác định). Mặc dù mã không sử dụng gì ngoại trừ loại được coi là loại "có kích thước cố định", tiêu chuẩn sẽ yêu cầu hai loại trình biên dịch khác nhau được sử dụng ngày nay sẽ mang lại hai kết quả khác nhau và nhiều trình biên dịch phổ biến hiện nay sẽ mang lại kết quả thứ ba.
Ví dụ cụ thể này hơi khó hiểu, trong đó tôi không mong đợi trong mã trong thế giới thực sẽ gán trực tiếp sản phẩm của hai giá trị 16 bit cho giá trị 64 bit, nhưng nó được chọn làm ví dụ ngắn gọn để hiển thị ba số nguyên chương trình khuyến mãi có thể tương tác với các loại không dấu được cho là có kích thước cố định. Có một số tình huống trong thế giới thực, trong đó toán học cần phải được thực hiện theo các quy tắc của số học toán học số nguyên, những trường hợp khác cần phải được thực hiện theo quy tắc của số học mô-đun và một số nơi thực sự không ' vấn đề Rất nhiều mã trong thế giới thực cho những thứ như tổng kiểm tra dựa trên uint32_t
gói số học 2³² và khi có thể thực hiện tùy ýuint16_t
số học và nhận được kết quả tối thiểu, được xác định là mod chính xác 65536 (trái ngược với việc kích hoạt Hành vi không xác định).
Mặc dù tình huống này rõ ràng có vẻ không mong muốn (và sẽ trở nên nhiều hơn khi xử lý 64 bit trở thành chuẩn mực cho nhiều mục đích), ủy ban tiêu chuẩn C từ những gì tôi quan sát thấy thích giới thiệu các tính năng ngôn ngữ đã được sử dụng trong một số sản phẩm đáng chú ý môi trường, thay vì phát minh ra chúng "từ đầu". Có bất kỳ tiện ích mở rộng đáng chú ý nào đối với ngôn ngữ C sẽ cho phép mã xác định không chỉ cách thức một loại sẽ được lưu trữ mà còn cách nó hoạt động trong các tình huống liên quan đến các chương trình khuyến mãi có thể không? Tôi có thể thấy ít nhất ba cách một phần mở rộng trình biên dịch có thể giải quyết các vấn đề như vậy:
Bằng cách thêm một lệnh sẽ hướng dẫn trình biên dịch buộc các loại số nguyên "cơ bản" nhất định phải có kích thước nhất định.
Bằng cách thêm một lệnh sẽ hướng dẫn trình biên dịch đánh giá các kịch bản quảng cáo khác nhau như thể các loại máy có kích thước cụ thể, bất kể kích thước thực tế của các loại trên kiến trúc đích.
Bằng cách cho phép các phương tiện khai báo các loại có các đặc điểm cụ thể (ví dụ: tuyên bố rằng một loại sẽ hoạt động như một vòng đại số bao bọc mod-65536, bất kể kích thước từ cơ bản và không được chuyển đổi hoàn toàn sang các loại khác; thêm một
wrap32
vàoint
sẽ mang lại một kết quả của loạiwrap32
bất kểint
lớn hơn 16 bit, trong khi thêmwrap32
trực tiếp vào mộtwrap16
nên là bất hợp pháp (vì không thể chuyển đổi sang loại khác).
Sở thích riêng của tôi sẽ là lựa chọn thay thế thứ ba, vì nó sẽ cho phép ngay cả các máy có kích thước từ bất thường hoạt động với nhiều mã dự kiến các biến sẽ "bao bọc" như với kích cỡ có hai kích thước; trình biên dịch có thể phải thêm các hướng dẫn che mặt bit để làm cho kiểu hoạt động phù hợp, nhưng nếu mã cần một kiểu bao bọc mod 65536, tốt hơn là để trình biên dịch tạo mặt nạ như vậy trên các máy cần nó hơn là làm lộn xộn mã nguồn với nó hoặc đơn giản là có mã như vậy bằng cách không sử dụng được trên các máy mà việc che dấu như vậy là cần thiết. Tuy nhiên, tôi tò mò liệu có bất kỳ tiện ích mở rộng phổ biến nào sẽ đạt được hành vi di động thông qua bất kỳ phương tiện nào ở trên không, hoặc thông qua một số phương tiện mà tôi chưa từng nghĩ tới.
Để làm rõ những gì tôi đang tìm kiếm, có một vài điều; đáng chú ý nhất:
Mặc dù có nhiều cách mà mã có thể được viết để đảm bảo ngữ nghĩa mong muốn (ví dụ: xác định các macro để thực hiện phép toán trên các toán hạng không dấu có kích thước cụ thể để mang lại kết quả rõ ràng là kết thúc hoặc không) hoặc ít nhất là ngăn chặn không mong muốn ngữ nghĩa (ví dụ như có điều kiện-định nghĩa một kiểu
wrap32_t
làuint32_t
trên các trình biên dịch, nơi mộtuint32_t
sẽ không được thăng tiến, và con số đó sẽ tốt hơn cho mã đòi hỏiwrap32_t
thất bại biên soạn trên máy nơi kiểu đó sẽ được thăng tiến hơn để có nó chạy và mang lại hành vi giả mạo), nếu có bất kỳ cách viết mã nào có thể chơi thuận lợi nhất với các phần mở rộng ngôn ngữ trong tương lai, sử dụng cách đó sẽ tốt hơn là nghĩ ra cách tiếp cận của riêng tôi.Tôi có một số ý tưởng khá vững chắc về cách ngôn ngữ có thể được mở rộng để giải quyết nhiều vấn đề kích thước nguyên, cho phép mã mang lại ngữ nghĩa giống hệt nhau trên các máy có kích thước từ khác nhau, nhưng trước khi tôi dành thời gian đáng kể để viết chúng, tôi muốn để biết những nỗ lực theo hướng đó đã được thực hiện.
Tôi không muốn bị coi là chê bai Ủy ban Tiêu chuẩn C hoặc công việc họ đã sản xuất; Tuy nhiên, tôi hy vọng rằng trong một vài năm, sẽ cần thiết để làm cho mã hoạt động chính xác trên các máy có loại quảng cáo "tự nhiên" sẽ có 32 bit, cũng như những nơi có 64 bit. Tôi nghĩ rằng với một số phần mở rộng khiêm tốn cho ngôn ngữ (khiêm tốn hơn nhiều thay đổi khác giữa C99 nnd C14), không chỉ có thể cung cấp một cách hiệu quả sử dụng kiến trúc 64 bit, mà trong giá cả cũng tạo điều kiện cho việc tương tác với các máy "có kích thước từ bất thường" mà tiêu chuẩn đã từng sử dụng để hỗ trợ [ví dụ: làm cho các máy có mã 12 bit có char
thể chạy mã mong đợiuint32_t
để quấn mod 2³²]. Tùy thuộc vào hướng mà các tiện ích mở rộng trong tương lai thực hiện, tôi cũng hy vọng có thể xác định các macro sẽ cho phép mã được viết ngày hôm nay có thể sử dụng được trên các trình biên dịch ngày nay trong đó các kiểu số nguyên mặc định hoạt động như "mong đợi", nhưng cũng có thể sử dụng trên các trình biên dịch trong tương lai các loại sẽ được mặc định hành xử khác nhau, nhưng nơi có thể cung cấp các hành vi cần thiết.
int
nào, nhưng nó vẫn lẻn vào. (Một lần nữa giả sử hiểu biết của tôi về tiêu chuẩn C là chính xác.)
int
lớn hơnuint16_t
, các toán hạng của phép nhân sẽ được thăng cấp lênint
và phép nhân sẽ được thực hiện dướiint
dạng phép nhân vàint
giá trị kết quả sẽ được chuyển đổi thànhint64_t
khởi tạowho_knows
.