Как инициализировать строку C 16-разрядным целым числом? - PullRequest
1 голос
/ 28 сентября 2011

Я хочу создать глобальную 22-символьную (+ NULL) строку в C. Я инициализирую ее так:

#define SVN_REVISION     "1143"
#define SERIAL_NUMBER    "PST3201109270001"
char general_info[23] = SVN_REVISION SERIAL_NUMBER SAMPLING_FREQUENCY;

Пока что все работает отлично.general_info инициализируется конкатенацией двух строк.Теперь, для последних двух символов, я хочу, чтобы они были 16-разрядными целыми числами.Но я не могу просто сделать это:

#define SVN_REVISION          "1143"
#define SERIAL_NUMBER         "PST3201109270001"
#define SAMPLING_FREQUENCY    (UINT16)500
char general_info[23] = SVN_REVISION SERIAL_NUMBER SAMPLING_FREQUENCY SAMPLING_FREQUENCY;

Что я могу сделать?

Ответы [ 4 ]

1 голос
/ 28 сентября 2011

Если вы хотите встроить 16-разрядное целое число 500 в качестве двоичных данных в конец строки, вы можете использовать необработанные шестнадцатеричные байты:

/* Little-endian unsigned 16-bit integer with the value 500 */
#define SAMPLING_FREQUENCY    "\xf4\x01"

Осторожно, но порядком байтов является архитектуразависимый, поэтому вы можете захотеть добавить дополнительный макрос для правильного упорядочения байтов в зависимости от архитектуры:

#ifdef ... /* little endian */
#define BYTES2(a,b) b a
#else ... /* big endian */
#define BYTES2(a,b) a b
#endif
#define SAMPLING_FREQUENCY    BYTES16("x01", "\xf4")

РЕДАКТИРОВАТЬ: Если вы хотите, чтобы число читалось человеком, выне может иметь его во время компиляции (по крайней мере, в C), но вы можете инициализировать его во время выполнения:

#define SVN_REVISION     "1143"
#define SERIAL_NUMBER    "PST3201109270001"
#pragma pack(push, 1)
union {
    struct {
        char svn_rev_serial[20];
        uint16_t freq;
        char nul;
    };
    char general_info[23];
} u = {{
    SVN_REVISION SERIAL_NUMBER,
    500,
    '\0'
}};
#pragma pack(pop)

При этом используются более нестандартные (но хорошо поддерживаемые) конструкции, такие как #pragma pack и писать одному члену профсоюза и читать другому.

1 голос
/ 28 сентября 2011

Вы должны использовать обычный трюк "stringify operator".

#define STRINGIFY_HELPER(str) #str
#define STRINGIFY(str) STRINGIFY_HELPER(str)

#define SVN_REVISION          "1143"
#define SERIAL_NUMBER         "PST3201109270001"
#define SAMPLING_FREQUENCY    (UINT16)500
char general_info[23] = SVN_REVISION SERIAL_NUMBER SAMPLING_FREQUENCY STRINGIFY(SAMPLING_FREQUENCY);

Для использования оператора препроцессора # необходим двойной макрос, поскольку аргументы макроса не раскрываются при использовании оператора #. Таким образом, требуется дополнительный макрос-шаг, чтобы сначала развернуть аргументы, а затем использовать оператор #. Хорошее объяснение можно найти здесь .

<ч />

редактировать

На самом деле, это не сработает из-за приведения (UINT16), который также будет преобразован в строку. Вы можете по-прежнему обходиться без макросов, только если можете позволить себе создание дополнительного макроса:

#define STRINGIFY_HELPER(str) #str
#define STRINGIFY(str) STRINGIFY_HELPER(str)

#define SVN_REVISION          "1143"
#define SERIAL_NUMBER         "PST3201109270001"
#define SAMPLING_FREQUENCY_NOCAST    500
#define SAMPLING_FREQUENCY    (UINT16)(SAMPLING_FREQUENCY_NOCAST)
char general_info[23] = SVN_REVISION SERIAL_NUMBER SAMPLING_FREQUENCY STRINGIFY(SAMPLING_FREQUENCY_NOCAST);

Это не очень элегантно, но вы все равно избегаете проблемы дублирования значения 500 (вам просто нужно обновить его в одном месте, и все будет работать нормально).

0 голосов
/ 28 сентября 2011

Вы можете попробовать что-то вроде:

#define SVN_REVISION          "1143"
#define SERIAL_NUMBER         "PST3201109270001"
#define SAMPLING_FREQUENCY    "\xF4\x1\00\00"
char general_info[29] = SVN_REVISION SERIAL_NUMBER SAMPLING_FREQUENCY SAMPLING_FREQUENCY;

\ xF4 \ x1 \ 00 \ 00 - представление памяти для десятичного числа 500 (по крайней мере, на платформах Windows)

0 голосов
/ 28 сентября 2011

Ну, вы можете попробовать это:

char general_info[23] = SVN_REVISION SERIAL_NUMBER SAMPLING_FREQUENCY;
strcat(genral_info, itoa(SAMPLING_FREQUENCY));
...