Czy można znaleźć rozmiary typów danych (int, float, double,…) w systemie, bez pisania programu w C?


19

Czy można znaleźć rozmiary typów danych (int, float, double, ...) w systemie Linux, bez pisania programu w języku C.

Czy wyniki dla C będą takie same jak dla C ++ i innych języków programowania w tym samym systemie Linux?


4
Jestem ciekawy - jeśli nie zamierzasz pisać programu w C, jaką to ma różnicę, jeśli typy danych C mają jeden rozmiar, a nie inny?
David Cary

7
@DavidCary Do wywoływania ABI z języka innego niż C!
Kaz

Odpowiedzi:


18

Jeśli znasz definicję typu danych, którego chcesz użyć, możesz getconfznaleźć te wartości w większości systemów uniksowych.

$ getconf CHAR_BIT
8

Lista zmiennych jest zdefiniowana zarówno na stronie man, man limits.hjak i tutaj, man sysconfoprócz tego, że znajduje się na dysku. Można używać locate limits.hgo znaleźć, to często tutaj: /usr/include/linux/limits.h.


4
Z zastrzeżeniem, że dotyczy to tylko oficjalnego kompilatora C platformy. Mogą istnieć alternatywne kompilatory lub alternatywne konfiguracje (zazwyczaj za pomocą opcji wiersza poleceń) oficjalnego kompilatora, które prowadzą do różnych rozmiarów.
Gilles „SO- przestań być zły”

@Gilles - czy kiedykolwiek widziałeś sposób, aby faktycznie wymienić te zmienne? Szukałem i nie mogę przez całe życie znaleźć narzędzia, które mogłoby to zrobić. Wygląda na to, że będzie. Miałem też wrażenie, że przejście przez te wartości getconfbyło najbezpieczniejszym sposobem, pod warunkiem, że mówisz, że uderzam w „oficjalny” kompilator na pudełku.
slm

3
Niezawodny sposób - i sposób, w jaki ludzie korzystają, kiedy im zależy, czyli zasadniczo, gdy chcą skompilować program w języku C - to skompilować mały program w języku C. Zobacz, jak działa autoconf. getconfnie jest tak bezpieczne, chyba że wywołujesz kompilator C jako c89lub c99z (prawie) bez opcji.
Gilles „SO- przestań być zły”

11

Rodzaj.

Przy przynajmniej gcc działa to:

$ cpp -dD /dev/null | grep __SIZEOF_LONG__

W każdym razie, dlaczego nie chcesz napisać programu C, aby to zrobić? Możesz wysłać mały kompilator C do swojego kompilatora z powłoki coś takiego:

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 cInformuje kompilator, język jest C, a -środki czytane ze standardowego wejścia.

W moim systemie powyższe wydruki:

int=4 bytes
long=8 bytes

Testowane w gcc i clang.


8

Tak. Możesz skanować/usr/include/<arch>/limits.h

Na przykład na moim amd64 NetBSD, /usr/include/amd64/limits.hpokaże:

#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
To często działa, ale czasami różne kompilatory lub ustawienia kompilatora prowadzą do różnych rozmiarów.
Gilles „SO- przestań być zły”

Kiedy patrzę na limit.h w Ubuntu, wskazuje na zmienne takie jak -SHRT_MAX-, których wartość jest uzyskiwana przez preprocesor C. Gdzie mogę to znaleźć?
Pan Doomsbuster,

8

Jeśli masz zainstalowany Perl, możesz uzyskać to z Perla -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

No ... to jest możliwe uruchamianie plików binarnych z różnymi ideami wielkości podstawowych typów, szczególnie w przypadku 64-bitowych architektur. Najnowsze jądra Linuksa na x86_64 mogą uruchamiać natywne 32-bitowe pliki binarne, a także x32 ABI z 32-bitowymi typami.

Rozmiary typów danych są częściowo tym, czego używa kompilator. Jest jednak wyraźnie korzystne (1) używanie typów obsługiwanych przez maszynę efektywnie i (2) używanie typów konsekwentnie z bibliotek niskiego poziomu poprzez aplikacje użytkownika. Konieczność obsługi kilku wariantów to po prostu bałagan.


6

Rozmiary typów danych są własnością kompilatora (lub ABI), a nie systemu. Możesz mieć wiele kompilatorów używających różnych rozmiarów dla typów danych w tym samym systemie.


0

Spróbuj to przeanalizować i wypisać wiersze zawierające ciągi odwołujące się do typów danych:

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

Łapie to oczywiście definicje, /usr/include/limits.hwięc dostaniesz to plus, czasem z wartościami, ale głównie odnosząc się do tego, co jest ustawione, w limits.hktórym możesz wygodnie przeglądać za pomocą poleceń getconf -ai ulimit -a.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.