Приведение типов массива в C

Я читал исходный код FFMPEG по извлечению аудио и нашел эти макросы. Что делают эти макросы?

#define REINTERPRET_CAST(type, variable) C_CAST(type, variable)
#define STATIC_CAST(type, variable) C_CAST(type, variable)
#define C_CAST(type, variable) ((type)variable)

//used like this
int value = 0;
int sampleIndex = 0;
uint8_t* buffer = calloc(50, sizeof(uint8_t));

value = REINTERPRET_CAST(uint8_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int16_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int32_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int64_t*, buffer)[sampleIndex];
int ret = STATIC_CAST(float, *REINTERPRET_CAST(double*, &value));

Пропустите код через препроцессор и посмотрите, во что расширяются макросы.

Some programmer dude 12.02.2023 20:29

Они просто расширяются до тех же обычных явных приведений. Их авторы, вероятно, определили их, чтобы отразить семантику приведения C++ и/или задокументировать причину, по которой приведения хорошо определены.

Brian 12.02.2023 20:30

Предполагая, что я ничего не упускаю, эти макросы просто бесполезны, и просто писать приведения вручную, вероятно, будет проще для всех.

AggelosT 12.02.2023 20:32

Я нуб. Простите меня за вопрос. Как бы я написал эти макросы вручную?

murage kibicho 12.02.2023 21:12
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
4
89
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
//используется вот так

Используемые, как в этом коде, они не делают ничего значимого - преобразуют указатель в int и присваивают int vartable (абстрагируясь от неправильного синтаксиса)

Если они используются так:

uint64_t value = *REINTERPRET_CAST(int64_t*, buffer + sampleIndex);

Кстати, макрос тоже неправильный

#define C_CAST(type, variable) ((type)(variable))

Затем это называется каламбуром указателя и вызывает Undefined Behavior, нарушая строгие правила псевдонимов.

Это должно быть сделано следующим образом:

#define pune(var, X) _Generic((var), \
              uint16_t *: pune16, \
              uint32_t *: pune32,  \
              uint64_t*: pune64  \
              )(var, X)


uint16_t pune16(uint16_t *val, const void *ptr)
{
    memcpy(val, ptr, sizeof(*val));
    return *val;
}

uint32_t pune32(uint32_t *val, const void *ptr)
{
    memcpy(val, ptr, sizeof(*val));
    return *val;
}

uint64_t pune64(uint64_t *val, const void *ptr)
{
    memcpy(val, ptr, sizeof(*val));
    return *val;
}

Пример использования:

void foo(void *v)
{
    uint32_t x;
    x = pune(&x, v);
    printf("%"PRIu32"\n,",  x);
}

«Это должно быть сделано так» не принимает во внимание [sampleIndex].

chux - Reinstate Monica 12.02.2023 20:43

@chux-ReinstateMonica buffer + sampleIndex не так ли?

0___________ 12.02.2023 20:46

Хм, OP [sampleIndex] включает добавление указателя целевого типа. buffer + sampleIndex — добавление указателя на исходный тип.

chux - Reinstate Monica 12.02.2023 20:49

@chux-ReinstateMonica Я не знаю, о чем ты говоришь buffer это определенно источник

0___________ 12.02.2023 20:50

@chux-ReinstateMonica, вы могли бы просто сказать, что исходный макрос плохой, а не эти комментарии

0___________ 12.02.2023 20:52
REINTERPRET_CAST(uint64_t*, buffer)[sampleIndex] похож на ((uint64_t*) buffer)[sampleIndex] и имеет доступ к другой части buffer[], чем pune64(buffer + sampleIndex);.
chux - Reinstate Monica 12.02.2023 20:54

@chux-ReinstateMonica, вы комментируете несуществующий код - ваш комментарий появился через много минут после моего редактирования.

0___________ 12.02.2023 21:01

Давайте продолжим обсуждение в чате.

chux - Reinstate Monica 12.02.2023 23:11

tstanisl 13.02.2023 14:40

@tstanisl ты не видел memcpy?

0___________ 13.02.2023 14:46

Я имею в виду, что нет необходимости играть в функции _Generic и puneN. Только memcpy будет достаточно.

tstanisl 13.02.2023 15:23

@tstanisl нет, потому что он также должен работать с указателями. Слишком много писать. Компилятор все равно удалит лишние назначения

0___________ 13.02.2023 15:52

Другие вопросы по теме