2016-03-28 2 views
2

Целые числа (из stdint.h) на самом деле типизируются для стандартных типов C. Таким образом, к ним также применяются «поощрения аргументов по умолчанию», которые применяются в переменных (varargs), таких как printf(), так что char и short передаются в int (подписанный или без знака).Целые числа и промо-роли в функциях varargs

Я пишу функцию, подобную printf, которая предназначена для целых чисел. Он имеет строку формата, которая имеет информацию о размере для всех целых чисел в списке аргументов переменных.

Как написать код запроса varargs, чтобы он извлекал каждый аргумент с правильным размером? Я полагаю, что моя функция должна быть осведомлена о продвижении аргументов по умолчанию, но они являются компиляторами/зависящими от системы, потому что это зависит от того, имеет ли система 16/32/64 бит int. Как я могу получить аргументы правильно, независимо от компилятора?

+0

"Как я могу получить аргументы прямо, в компиляторе-независимым образом?" ну, иначе, чем из документации по платформе, которую вы предоставили. – Shark

+0

Я не совсем уверен, в чем проблема - разве это не то, что означает 'va_arg'? –

+0

В чем проблема при использовании 'va_arg'? –

ответ

3

Чтобы определить, есть ли some type становится int, unsigned или остается тот же самый тип, когда передается функции с ..., код может использовать _Generic(). (C99 или более поздняя версия)

Используя *1, это подражает обычным акциям, снятым с помощью f(format, ...).

Теперь ваш Printf-как функция может определить, является ли аргумент был назначен int, unsigned или оставить как есть.

#include <stdio.h> 
#define PromoType(v) _Generic(v*1, \ 
    unsigned : "unsigned", \ 
    int : "int", \ 
    default: "no change" \ 
) 

int main(void) { 
    int16_t i16; 
    puts(PromoType(i16)); 
    uint16_t u16; 
    puts(PromoType(u16)); 
    int32_t i32; 
    puts(PromoType(i32)); 
    uint32_t u32; 
    puts(PromoType(u32)); 
    int64_t i64; 
    puts(PromoType(i64)); 
    uint64_t u64; 
    puts(PromoType(u64)); 
    return 0; 
} 

Выход

int 
int 
int 
unsigned 
no change 
no change 
+0

Большое спасибо, chux. Это решает мой вопрос. Во всяком случае, я напишу несколько кодов кода, потому что время от времени мне нужно создать свой код со старыми компиляторами, которые могут не поддерживать C99. Я нашел расширение типа GCC, которое может быть альтернативой этому.И в случае, если компилятор не поддерживает C99 и не является GCC, я буду использовать метод sizeof(), предложенный Оливером Чарлворт выше. Благодаря! – cesss