Перечислите основные типы данных в C, чтобы можно было легко получить доступ к размерам - PullRequest
0 голосов
/ 01 июля 2018

Можно ли получить размеры всех основных типов данных в C, используя цикл for? Например, можем ли мы сделать что-то подобное?

#include <datatypes.h> /* or something else which defines get_data_types() */
#include <stdio.h>

int main() {
    for (int x = 0; x < len(get_data_types()); x++) {
        printf("Size of %s is %d", get_data_types()[x], sizeof(get_data_types()[x]));
    }
 }

Я мог бы перечислить все типы данных, заменив цикл for и записав отдельные операторы для int, long и т. Д. Однако мне интересно, возможно ли использовать цикл for для того же самого?

По сути, я стараюсь избегать следующего:

#include <stdio.h>

int main() {
    printf("Size of int is %d", sizeof(int);
    printf("Size of unsigned int is %d", sizeof(unsigned int);
    printf("Size of long is %d", sizeof(long);
    /* etc. */
    return 0;
}

Интересующие типы данных - char, unsigned char, signed char, int, unsigned int, short, unsigned short, long, unsigned long, float, double, long double

Уточнение : Я не обязательно хочу массив смешанных типов, но чтобы иметь возможность перечислять типы так, чтобы размеры были легко доступны.

Ответы [ 3 ]

0 голосов
/ 01 июля 2018

Ваш подход невозможен, различные типы должны перечисляться явно, так или иначе, но вы можете создать массив структур, использовать вспомогательный макрос для простой инициализации и написать цикл для вывода всех стандартных размеров типов.

Обратите внимание, что вы забыли несколько полезных стандартных типов:

  • более целых типов: long long, unsigned long long, size_t, ptrdiff_t, intmax_t, uintmax_t, wchar_t ...
  • типы указателей: void *, char *, int * ...
  • типы указателей на функции: void(*)(void)

Вот реализация:

#include <inttypes.h>
#include <stddef.h>
#include <stdio.h>

#define TYPEDESC(t)  { #t, sizeof(t) }

static struct type_desc {
    const char *name;
    int size;
} const types[] = {
    TYPEDESC(char), TYPEDESC(unsigned char), TYPEDESC(signed char),
    TYPEDESC(wchar_t),
    TYPEDESC(short), TYPEDESC(unsigned short),
    TYPEDESC(int), TYPEDESC(unsigned int),
    TYPEDESC(long), TYPEDESC(unsigned long),
    TYPEDESC(long long), TYPEDESC(unsigned long long),
    TYPEDESC(float), TYPEDESC(double), TYPEDESC(long double),
    TYPEDESC(size_t), TYPEDESC(ptrdiff_t),
    TYPEDESC(intmax_t), TYPEDESC(uintmax_t),
    TYPEDESC(void *), TYPEDESC(char *), TYPEDESC(int *),
    TYPEDESC(void (*)(void)),
};

int main() {
    size_t i;
    for (i = 0; i < sizeof(types) / sizeof(types[0]); i++)
        printf("sizeof( %s ) = %d\n", types[i].name, types[i].size);
    return 0;
}

Вывод на моей 64-битной системе OS / X такой:

sizeof( char ) = 1
sizeof( unsigned char ) = 1
sizeof( signed char ) = 1
sizeof( wchar_t ) = 4
sizeof( short ) = 2
sizeof( unsigned short ) = 2
sizeof( int ) = 4
sizeof( unsigned int ) = 4
sizeof( long ) = 8
sizeof( unsigned long ) = 8
sizeof( long long ) = 8
sizeof( unsigned long long ) = 8
sizeof( float ) = 4
sizeof( double ) = 8
sizeof( long double ) = 16
sizeof( size_t ) = 8
sizeof( ptrdiff_t ) = 8
sizeof( intmax_t ) = 8
sizeof( uintmax_t ) = 8
sizeof( void * ) = 8
sizeof( char * ) = 8
sizeof( int * ) = 8
sizeof( void (*)(void) ) = 8

Может быть сюрпризом, что wchar_t имеет 32 бита и long double 16 байт. Это не означает, что значения long double используют все 128 битов для представления с плавающей запятой. Вывод будет очень отличаться в системе Windows.

0 голосов
/ 01 июля 2018

Ответ Клутта может быть немного упрощен до:

struct {
    char *name;
    int size;
} types[] = {
    {"int", sizeof(int)},
    {"char", sizeof(char)},
    {"long", sizeof(long)}
    //.. etcetera
};

int main(void) {
    int i;
    for (i=0; i<sizeof(types)/sizeof(types[0]); i++)
        printf("sizeof %s = %d\n",types[i].name, types[i].size);
    return 0;
}
0 голосов
/ 01 июля 2018

Нет, это невозможно. Нет никакого способа автоматически перечислить все типы в C. Вы должны сделать это вручную для каждого типа.

Однако, если вы много используете информацию, вы всегда можете подготовить список заранее. Есть несколько способов сделать это. Это один:

#include <stdio.h>
#include <string.h>

typedef struct {
    char name[20];
    int size;
} type;

int main()
{
    type types[3] = { {"int", sizeof (int) },
                      {"char", sizeof (char) },
                      {"double", sizeof (double) } };

    for (int x = 0; x<sizeof(types)/sizeof(types[0]); x++)
        printf("Size of %s is %d\n", types[x].name, types[x].size);
}

(Код упрощен благодаря вдохновению от ответа Пола Огилви ниже.)

В комментарии к этому ответу вы спросили: Можем ли мы просто создать массив, подобный следующему: types_array = {"int", "char", "double", "long"} и, повторяя это, получить соответствующие размеры? Я хочу сказать, используя некоторую функцию f, можем ли мы присвоить типы [j] .size для sizeof (f (types_array [j])) *

Короче, нет. Это потому, что C - это строго типизированный скомпилированный язык В таких языках, как Python и PHP, вы можете делать все подобные вещи, но в C нет. Не без обмана. Функция f в вашем примере должна иметь указанный тип возвращаемого значения, и этот тип sizeof получит в качестве аргумента.

Один из способов обойти это - написать нестандартный размер:

int mysizeof(char * s) {
    if(strcmp(s, "char") == 0)
        return sizeof(char);
    if(strcmp(s, "int") == 0)
        return sizeof(int);
}

Если этот список длинный, вы можете использовать макрос:

#define MYSIZEOF(x) if(strcmp(s, #x) == 0) return sizeof(x)

int mysizeof(char * s) {
    MYSIZEOF(int);
    MYSIZEOF(char);
    MYSIZEOF(double);
}
...