Tại sao mọi người đánh máy trên các loại C tiêu chuẩn?


103

Nếu bạn muốn sử dụng Qt , bạn phải nắm lấy quint8, quint16v.v.

Nếu bạn muốn sử dụng GLib , bạn phải chào đón guint8, guint16v.v.

Trên Linuxu32, s16v.v.

uC / OS định nghĩa SINT32, UINT16v.v.

Và nếu bạn phải sử dụng một số kết hợp của những thứ đó, bạn nên chuẩn bị cho những rắc rối. Bởi vì trên máy tính của bạn u32sẽ typedefkết thúc longquint32sẽ typedefkết thúc intvà trình biên dịch sẽ phàn nàn .

Tại sao mọi người làm điều này, nếu có <stdint.h>? Đây có phải là một kiểu truyền thống cho các thư viện?


8
@Mehrdad trong lập trình vi điều khiển, bạn có thể có đủ thứ. Ví dụ trên AVR Mega's (và do đó trên Arduino nổi tiếng) int là 16 bit. Đó có thể là một sự ngạc nhiên khó chịu. Theo ý kiến ​​của tôi, 'unsigned short' cần nhiều nỗ lực đánh máy hơn. Và nó luôn làm tôi buồn khi sử dụng 'unsigned char' cho <s> byte </s> octet. Ký tự không dấu, thực sự?
Amomum

2
@Mehrdad Vấn đề là bạn không thể thực sự chắc chắn. Đó chính xác là lý do tại sao stdint.hđược phát minh.
glglgl,

1
@glglgl: Đây là một cách khác để xem xét vấn đề: bạn không hỏi chính xác câu hỏi sao? Nếu bạn đang nhắm mục tiêu đến nhiều hệ thống, tại sao lại tự ý viết mã số bit vào mã ngay từ đầu? tức là, tại sao không chỉ nói sizeof(int) * CHAR_BIT(ví dụ) và sử dụng điều đó? Nếu của bạn intquá nhỏ để đại diện cho phạm vi của bạn (ví dụ: chỉ số mảng), thì bạn gần như chắc chắn không nên sử dụng intdù sao, nhưng một cái gì đó giống như size_t. Tại sao sẽ int32có ý nghĩa hơn? Thời gian duy nhất cố định chiều rộng có ý nghĩa là để giao tiếp giữa các hệ thống (ví dụ như tập tin định dạng / mạng) ...
user541686

1
@Mehrdad Không. Đôi khi tôi có các giá trị (chẳng hạn như từ ADC hoặc bất cứ thứ gì) mà tôi cần lưu trữ. Tôi biết chúng rộng 16 bit. Vì vậy, ting tốt nhất để sử dụng là uint16_t(hoặc có thể fasthoặc leastbiến thể của nó ). Quan điểm của tôi là: Những loại này rất thuận tiện để sử dụng và có lý do tồn tại của chúng.
glglgl,

1
@Mehrdad: Tôi đề nghị rằng - giả sử bạn có vẻ xứng đáng với nỗ lực tạo ra mã chất lượng - bạn nên xác định các typedef chức năng của riêng mình, nghĩa là cách tương tác với API của tôi / phần còn lại của mã của tôi và xác định chúng trên cơ sở kỹ thuật về Các typedef "kỹ thuật" như size_tvà / hoặc uint64_t.
PJTraill

Câu trả lời:


80

stdint.hkhông tồn tại trở lại khi những thư viện này đang được phát triển. Vì vậy, mỗi thư viện đã tạo ra các typedefs của riêng mình .


4
Và được rồi, tôi cho rằng việc thiếu stdint.h là một lý do chính đáng, nhưng tại sao ngay cả ngày nay những typedef này cũng vượt quá int, long và như vậy cho và không quá các loại stdint? Nó sẽ làm cho họ hoán đổi cho nhau ít nhất
Amomum

25
@Amomum "Tại sao Glib (được phát triển trên Linux) không sử dụng Linux typedefs?" Mặc dù "cơ sở chính" của glib chắc chắn là Linux, nhưng chắc chắn là do thiết kế một thư viện di động. Việc xác định các kiểu riêng của nó đảm bảo tính di động: Người ta chỉ phải điều chỉnh một tiêu đề nhỏ phù hợp với các loại thư viện với các loại nền tảng đích tương ứng thích hợp.
Peter - Khôi phục Monica

3
@Amomum Tại sao Glib (được phát triển trên Linux) ... Không, không phải vậy. Glib đã được tạo ra cách trước khi hạt nhân Linux.
andy256,

5
@ andy256 "GLib" không phải là viết tắt của "glibc". Đó là một thư viện được phân nhánh từ gtk. Nó không cũ hơn Linux.

2
@ andy256: glib là 1998, linux là 1991. IOW, GLib được tạo ra sau Linux.
MSalters

40

Đối với các thư viện cũ, điều này là cần thiết vì tiêu đề trong câu hỏi ( stdint.h) không tồn tại.

Tuy nhiên, vẫn còn một vấn đề xung quanh: những loại đó ( uint64_tvà những loại khác) là một tính năng tùy chọn trong tiêu chuẩn. Vì vậy, một triển khai tuân thủ có thể không đi kèm với chúng - và do đó buộc các thư viện vẫn phải đưa chúng vào ngày nay.


14
Các uintN_tloại là tùy chọn, nhưng loại uint_leastN_tuint_fastN_tthì không.
Kusalananda

7
@Kusalananda: Đáng buồn thay, những thứ đó lại có hạn.
Các cuộc đua ánh sáng trong quỹ đạo vào

16
Tất nhiên lý do mà họ không bắt buộc là bạn đang không được bảo đảm rằng có số nguyên loại với chính xác điều đó số bit. C vẫn hỗ trợ các kiến ​​trúc có kích thước số nguyên khá kỳ lạ.
celtschk

5
@LightnessRacesinOrbit: Chúng có tính hữu dụng hạn chế như thế nào? Tôi phải thừa nhận rằng ngoài các giao diện phần cứng, tôi không thấy lý do tại sao bạn sẽ cần một con số chính xác của các bit, thay vì chỉ ở mức tối thiểu, để đảm bảo tất cả các giá trị của bạn phù hợp.
celtschk

23
@Amomum Các typedef bắt buộc nếu việc triển khai có các kiểu đáp ứng yêu cầu: "Tuy nhiên, nếu một triển khai cung cấp các kiểu số nguyên với độ rộng 8, 16, 32 hoặc 64 bit, không có bit đệm và (đối với các kiểu có dấu) có biểu diễn phần bù của một hai, nó sẽ xác định các tên typedef tương ứng. " (trích dẫn từ N1570, 7.20.1.1 "Các kiểu số nguyên chiều rộng chính xác") Vì vậy, nếu thư viện tiêu chuẩn không có chúng, thì có vẻ như thư viện của bên thứ ba cũng không thể.
Eric M Schmidt,

13

stdint.h đã được chuẩn hóa từ năm 1999. Có nhiều khả năng là nhiều ứng dụng xác định các kiểu (bí danh hiệu quả) để duy trì sự độc lập từng phần khỏi kiến ​​trúc máy cơ bản.

Chúng cung cấp cho các nhà phát triển sự tin tưởng rằng các loại được sử dụng trong ứng dụng của họ phù hợp với các giả định cụ thể của dự án về hành vi có thể không phù hợp với tiêu chuẩn ngôn ngữ hoặc việc triển khai trình biên dịch.

Thực hành này được phản ánh trong mẫu thiết kế Façade hướng đối tượng và bị các nhà phát triển lạm dụng nhiều khi viết các lớp trình bao bọc cho tất cả các thư viện đã nhập.

Khi các trình tuân thủ ít tiêu chuẩn hơn nhiều và kiến ​​trúc máy có thể thay đổi từ các máy tính lớn có độ dài từ 16 bit, 18 bit đến 36 bit, điều này cần được xem xét nhiều hơn. Hiện nay, thực tế ít liên quan hơn nhiều trong một thế giới hội tụ các hệ thống nhúng ARM 32-bit. Nó vẫn là một mối quan tâm đối với các bộ vi điều khiển cấp thấp với bản đồ bộ nhớ lẻ .


1
Được cấp phép, stdint.hđã được chuẩn hóa từ năm 1999, nhưng nó đã có sẵn trong thực tế được bao lâu? Mọi người cố gắng thực hiện và áp dụng các tiêu chuẩn mới, và trong giai đoạn chuyển tiếp dài đó, các phương pháp cũ vẫn là điều bắt buộc.
Siyuan Ren

1
Một vấn đề khó chịu stdint.hlà ngay cả trên các nền tảng mà ví dụ longint32_tcó cùng kích thước và cách biểu diễn, không có yêu cầu nào về việc truyền một int32_t*đến long*sẽ mang lại một con trỏ có thể truy cập đáng tin cậy a int32_t. Tôi không thể tin rằng các tác giả của Tiêu chuẩn nghĩ rằng rõ ràng là các loại tương thích với bố cục phải tương thích với bí danh, nhưng vì họ không bận tâm đến việc nói nên các tác giả của gcc và IIRC clang nghĩ rằng ngôn ngữ sẽ được cải thiện bằng cách bỏ qua cả bí danh trong những trường hợp rõ ràng.
supercat

2
@supercat - đó có thể là giá trị trên Facebook Chia như một lỗi thuộc về cho ban C ... bởi vì đó là cách nhưng không câm , để đặt nó nhẹ
LThode

@LThode: Để ủy ban C thừa nhận rằng đó là một sai lầm sẽ yêu cầu họ chính thức tuyên bố hành vi của clang và gcc là sai lầm. Bạn có nghĩ rằng điều đó sẽ xảy ra? Điều tốt nhất có thể hy vọng (và IMHO là cách hợp lý để tiến hành) là xác định các cách để các chương trình chỉ định "chế độ răng cưa". Nếu một chương trình cho biết chỉ định rằng nó có thể chấp nhận các quy tắc răng cưa rất nghiêm ngặt, thì một trình biên dịch có thể sử dụng điều đó để cho phép tối ưu hóa vượt quá những gì hiện có thể. Nếu một chương trình quy định cụ thể mà nó đòi hỏi quy tắc có hơi nhiều lập trình viên thân thiện hơn so với những người có mặt ...
supercat

... nhưng vẫn sẽ cho phép nhiều tối ưu hóa hữu ích, sau đó một trình biên dịch có thể tạo ra mã hiệu quả hơn nhiều so với khả năng có thể -fno-strict-alias, nhưng nó vẫn sẽ thực sự hoạt động. Ngay cả khi không có cơ sở mã hiện có, không có bộ quy tắc nào có thể đạt được sự cân bằng tối ưu về tối ưu hóa và ngữ nghĩa cho tất cả các ứng dụng, bởi vì các ứng dụng khác nhau có nhu cầu khác nhau. Thêm vào cơ sở mã hiện có và nhu cầu về các chế độ khác nhau phải rõ ràng.
supercat

3

Vì vậy, bạn có quyền gõ char char thành int.

Một "kinh dị về mã hóa" đã đề cập rằng một tiêu đề của công ty có một điểm mà một lập trình viên muốn có một giá trị boolean và một char là kiểu gốc hợp lý cho công việc, và như vậy đã viết typedef bool char. Sau đó, một người nào đó đã tìm thấy một số nguyên là sự lựa chọn hợp lý nhất và đã viết typedef bool int. Kết quả là hầu như có tuổi trước Unicode typedef char int.

Tôi nghĩ là có khá nhiều tư duy về tương lai, tương thích về phía trước.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.