Có thể tìm ra kích thước của các loại dữ liệu (int, float, double, trên) trên một hệ thống mà không cần viết chương trình C không?


19

Có thể tìm ra kích thước của các loại dữ liệu (int, float, double, ...) trên hệ thống Linux mà không cần viết chương trình C không?

Các kết quả cho C giống như với C ++ và các ngôn ngữ lập trình khác trong cùng hệ thống Linux?


4
Tôi tò mò - nếu bạn không có ý định viết chương trình C, thì nó có gì khác biệt nếu các kiểu dữ liệu C có một kích thước chứ không phải một kích thước khác?
David Cary

7
@DavidCary Để gọi ABI từ một ngôn ngữ khác C!
Kaz

Câu trả lời:


18

Nếu bạn biết định nghĩa của kiểu dữ liệu bạn muốn, bạn có thể sử dụng getconfđể tìm các giá trị này trên hầu hết các hệ thống Unix.

$ getconf CHAR_BIT
8

Danh sách các biến được định nghĩa trong trang man man limits.hcũng như ở đây, man sysconfngoài việc nằm trên đĩa. Bạn có thể sử dụng locate limits.hđể tìm thấy nó, nó thường ở đây : /usr/include/linux/limits.h.


4
Với sự cảnh báo rằng điều này chỉ áp dụng cho trình biên dịch C chính thức của nền tảng. Có thể có các trình biên dịch thay thế hoặc các cấu hình thay thế (thường thông qua các tùy chọn dòng lệnh) của trình biên dịch chính thức, dẫn đến các kích thước khác nhau.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles - bạn đã bao giờ thấy một cách để thực sự liệt kê các biến này chưa? Tôi đã tìm kiếm và không thể tìm thấy một công cụ có thể làm điều này. Có vẻ như sẽ có. Ngoài ra, tôi có ấn tượng rằng việc vượt qua các giá trị getconfnày là cách an toàn nhất, miễn là bạn nói, tôi đang nhấn "trình biên dịch chính thức" trên hộp.
slm

3
Cách đáng tin cậy - và cách mọi người sử dụng khi họ quan tâm, thường là khi họ muốn biên dịch chương trình C - là biên dịch một chương trình C nhỏ. Xem cách autoconf hoạt động. getconfkhông an toàn lắm, trừ khi bạn gọi trình biên dịch C là c89hoặc c99gần như không có tùy chọn.
Gilles 'SO- ngừng trở nên xấu xa'

11

Loại.

Với gcc ít nhất, điều này hoạt động:

$ cpp -dD /dev/null | grep __SIZEOF_LONG__

Dù sao, tại sao bạn không muốn viết một chương trình C để làm điều đó? Bạn có thể gửi một chương trình C nhỏ đến trình biên dịch của mình từ trình bao như thế này:

binary=$(mktemp)
cat <<\EOF | cc -o $binary -x c -
#include <stdio.h>
int main() {
    printf("int=%lu bytes\n", sizeof(int));
    printf("long=%lu bytes\n", sizeof(long));
}
EOF
$binary
rm $binary

-x ccho trình biên dịch biết ngôn ngữ C-phương tiện được đọc từ đầu vào tiêu chuẩn.

Trên hệ thống của tôi, các bản in trên:

int=4 bytes
long=8 bytes

Đã thử nghiệm trong gcc và clang.


8

Vâng. Bạn có thể quét/usr/include/<arch>/limits.h

Ví dụ: trên NetBSD amd64 của tôi, /usr/include/amd64/limits.hsẽ hiển thị:

#define CHAR_BIT        8               /* number of bits in a char */

#define SCHAR_MAX       0x7f            /* max value for a signed char */
#define SCHAR_MIN       (-0x7f-1)       /* min value for a signed char */

#define UCHAR_MAX       0xff            /* max value for an unsigned char */
#define CHAR_MAX        0x7f            /* max value for a char */
#define CHAR_MIN        (-0x7f-1)       /* min value for a char */

#define USHRT_MAX       0xffff          /* max value for an unsigned short */
#define SHRT_MAX        0x7fff          /* max value for a short */
#define SHRT_MIN        (-0x7fff-1)     /* min value for a short */

#define UINT_MAX        0xffffffffU     /* max value for an unsigned int */
#define INT_MAX         0x7fffffff      /* max value for an int */
#define INT_MIN         (-0x7fffffff-1) /* min value for an int */

#define ULONG_MAX       0xffffffffffffffffUL    /* max value for an unsigned long */
#define LONG_MAX        0x7fffffffffffffffL     /* max value for a long */
#define LONG_MIN        (-0x7fffffffffffffffL-1)        /* min value for a long */

4
Điều này thường hoạt động, nhưng đôi khi các trình biên dịch hoặc cài đặt trình biên dịch khác nhau sẽ dẫn đến các kích thước khác nhau.
Gilles 'SO- ngừng trở nên xấu xa'

Khi tôi nhìn vào các giới hạn.h trong ubfox, nó chỉ vào các biến như -SHRT_MAX-, có giá trị được lấy từ bộ xử lý trước C. Tôi có thể tìm thấy nó ở đâu?
Ông Doomsbuster

8

Nếu bạn đã cài đặt perl, bạn có thể lấy cái này từ perl -V:

intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=8, prototype=define

6

Không ... nó có thể chạy mã nhị phân với những ý tưởng khác nhau của các kích thước của các loại cơ bản, đặc biệt là trên 64 bit, kiến trúc. Các hạt nhân Linux gần đây trên x86_64 có thể chạy các nhị phân 32 bit gốc và có x32 ABI với các loại 32 bit.

Các kích thước kiểu dữ liệu là một phần những gì trình biên dịch sử dụng. Nhưng rõ ràng có lợi cho (1) các loại sử dụng mà máy hỗ trợ hiệu quả và (2) sử dụng các loại nhất quán từ các thư viện cấp thấp thông qua các ứng dụng của người dùng. Phải xử lý một số biến thể chỉ là một mớ hỗn độn.


6

Kích thước của các loại dữ liệu là một thuộc tính của trình biên dịch (hoặc ABI), không phải của hệ thống. Bạn có thể có nhiều trình biên dịch sử dụng các kích cỡ khác nhau cho các loại dữ liệu trên cùng một hệ thống.


0

Hãy thử điều này để phân tích và xuất các dòng chứa các chuỗi tham chiếu các kiểu dữ liệu:

{ shopt -s globstar; for i in /usr/include/**/*.h; do grep -HE '\b(([UL])|(UL)|())LONG|\bFLOAT|\bDOUBLE|\bINT' $i; done; }

Điều này tất nhiên nắm bắt được các định nghĩa /usr/include/limits.hđể bạn sẽ nhận được nhiều hơn, đôi khi có các giá trị, nhưng chủ yếu là tham khảo những gì được đặt trong limits.hđó bạn có thể thuận tiện xem bằng các lệnh getconf -aulimit -a.

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.