Установите значение FourCC в C ++ - PullRequest
5 голосов
/ 01 мая 2009

Я хочу установить значение FourCC в C ++, то есть 4-байтовое целое число без знака.

Полагаю, очевидным способом является #define, например

#define FOURCC(a,b,c,d) ( (uint32) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) )

и затем:

uint32 id( FOURCC('b','l','a','h') );

Какой самый элегантный способ сделать это?

Ответы [ 11 ]

16 голосов
/ 01 мая 2009

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

template <int a, int b, int c, int d>
struct FourCC
{
    static const unsigned int value = (((((d << 8) | c) << 8) | b) << 8) | a;
};

unsigned int id(FourCC<'a', 'b', 'c', 'd'>::value);

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

8 голосов
/ 01 мая 2009
uint32_t FourCC = *((uint32_t*)"blah");

Почему не это?

РЕДАКТИРОВАТЬ: int -> uint32_t.

И нет, это не приводит символ ** к uint32_t. Он преобразует (char *) в (uint32_t *), а затем разыменовывает (uint32_t *). В этом нет никакого порядка байтов, так как он назначает uint32_t для uint32_t. Единственными недостатками являются выравнивание, и я не указал явно 32-битный тип.

5 голосов
/ 01 мая 2009

или сделать то же самое с помощью встроенной функции

inline uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
     return ( (uint32) (((d)<<24) | (uint32_t(c)<<16) | (uint32_t(b)<<8) | uint32_t(a)) )
} 

и избегайте головной боли макроса, но в остальном ваш подход мне подходит.

3 голосов
/ 15 декабря 2014

Используя C ++ 11 constexpr, вы можете написать что-то вроде:

constexpr uint32_t fourcc( char const p[5] )
{
    return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}

А затем используйте его как:

fourcc( "blah" );

Плюсы:

  • более читабельно,
  • если строковый аргумент известен во время компиляции, то функция оценивается во время компиляции (без накладных расходов во время выполнения).
  • не зависит от порядкового номера (т. Е. Первый символ аргумента всегда будет находиться в старшем старшем байте fourcc).

минусы:

  • Требуется компилятор c ++ 11 (или более поздней версии).
3 голосов
/ 01 мая 2009

Если я не ошибаюсь, вы можете просто использовать константы из нескольких символов для этого права?

unsigned int fourCC = 'blah';

Это совершенно верно для спецификации ANSI / ISO, хотя некоторые компиляторы будут немного жаловаться. Вот как типы ресурсов использовались в более старых API Macintosh.

1 голос
/ 01 мая 2009

Если константа времени компиляции не требуется, возможно, самая близкая -

unsigned int FourCCStr(const char (&tag)[5])
{
    return (((((tag[3] << 8 ) | tag[2]) << 8) | tag[1]) << 8) | tag[0];
}

#define FOURCC(tag) FourCCStr(#tag)

unsigned int id(FOURCC(blah));

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

1 голос
/ 01 мая 2009

Предполагая, что Windows (как FOURCC - это концепция Windows), Win API уже предоставляет mmioStringToFOURCC и mmioFOURCC .

1 голос
/ 01 мая 2009

Я не вижу ничего плохого в вашем алгоритме. Но для чего-то подобного я бы просто написал функцию вместо макроса. Макросы имеют множество скрытых функций / проблем, которые могут со временем вас укусить

uint FourCC(char a, char b, char c, char d) { 
  return ( (uint32) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) );
}
0 голосов
/ 22 августа 2013

Как насчет:

#if BYTE_ORDER == BIG_ENDIAN
#define FOURCC(c0,c1,c2,c3) ((uint32) ((((uint32)((uint8)(c0)))<<24) +(((uint32)((uint8)(c1)))<<16)+ (((uint32)((uint8)(c2)))<<8) + ((((uint32)((uint8)(c3)))))) 
#else
#if BYTE_ORDER == LITTLE_ENDIAN
#define FOURCC(c3,c2,c1,c0) ((uint32) ((((uint32)((uint8)(c0)))<<24) +(((uint32)((uint8)(c1)))<<16)+ (((uint32)((uint8)(c2)))<<8) + ((((uint32)((uint8)(c3)))))) 
#else
#error BYTE_ORDER not defined
#endif
#endif
0 голосов
/ 01 мая 2009
uint32 fcc(char * a)
{   
    if( strlen(a) != 4)
        return 0;       //Unknown or unspecified format

    return 
    (
            (uint32) 
            ( 
                ((*(a+3))<<24) |
                ((*(a+2))<<16) |
                ((*(a+1))<<8) | 
                (*a)
            )       
    );
}
...