2015-02-28 4 views
1

У меня есть функция преобразования десятичного числа в восьмеричное, и я хотел бы называть ее либо int, либо unsigned int в зависимости от некоторых параметров. Моя первая мысль заключалась в том, чтобы скопировать/вставить код и просто изменить тип параметра ... есть ли лучший способ?Типы аргументов Differents для одной и той же функции

+2

См [функция перегрузка] (http://stackoverflow.com/q/479207/1366431) для обсуждения одного (не обязательно наилучшего) подхода , – Leushenko

ответ

1

Ну, если вам нужно сделать перегрузку на C, у вас есть три варианта.

  1. Внесите VFT свое «я». Существует много способов создания VFT и вызова соответствующей функции в зависимости от того, что вы хотите сделать. Просто сделайте проверку для OO в C
  2. Используйте препроцессор. Вы можете использовать агностические процедуры типа в препроцессоре. Но вам придется делать много проверок для типа аргументов или применять процедуры, которые также являются агностиками типа.
  3. Используйте аргумент, чтобы предоставить вам случай. У вас может быть функция-обертка с тремя аргументами; основные два аргумента, возможно, указатели типа void, и один из типов string, enum, определенных в препроцессоре или других подобных ситуациях. В зависимости от последнего вы будете делать приемы типов и вызывать соответствующую функцию самостоятельно.

Или ... вы могли бы использовать struct/union (в виде объекта как мода) и в зависимости от его характеристик выполнять соответствующие вычисления. Но я думаю, что для того, что вы должны сделать, этот последний подход был бы слишком большим. На самом деле все было бы слишком много. Что бы я сделал, было бы иметь одну функцию с указателем void как первый аргумент, указатель на вывод и третий аргумент, определяющий тип первого аргумента. Процесс тот же, но у вас разные пределы, которые могут вызвать переполнение в крайних или отрицательных значениях. Таким образом, по третьему аргументу вы будете вызывать первый указатель void и делать преобразование.

+0

Как вы должны знать, подписано или нет знака целого, проверяя его значение? :) Вы не знаете, подписан ли он или нет, поэтому вы не знаете, как интерпретировать значение. «Над пределами подписанного int» - это то же самое, что «если это отрицательно». (С двумя дополнениями, которые по крайней мере.) – Jite

+0

Да, @Jite. Ты прав. Фактически я сделал редактирование, прежде чем я увижу ваш комментарий. – Xxxo

+0

Мне нравится метод указателей void, спасибо :) – Willy

2

Вы можете использовать союзы:

#include <stdio.h> 

enum octal_type {AS_INT, AS_UINT}; 

typedef union { 
    int as_int; 
    unsigned as_uint; 
} t_octal; 

void fn(t_octal value, enum octal_type type) 
{ 
    switch (type) { 
     case AS_INT: 
      printf("%d\n", value.as_int); 
      break; 
     case AS_UINT: 
      printf("%u\n", value.as_uint); 
      break; 
    } 
} 

int main(void) 
{ 
    t_octal value; 

    value.as_int = 5; 
    fn(value, AS_INT); 
    return 0; 
} 

Или общие указатели:

#include <stdio.h> 

enum octal_type {AS_INT, AS_UINT}; 

void fn(const void *value, enum octal_type type) 
{ 
    switch (type) { 
     case AS_INT: 
      printf("%d\n", *(int *)value); 
      break; 
     case AS_UINT: 
      printf("%u\n", *(unsigned *)value); 
      break; 
    } 
} 

int main(void) 
{ 
    int value = 5; 

    fn(&value, AS_INT); 
    return 0; 
} 

Под C11 вы можете ommit второй параметр в вызове с помощью _Generic:

#include <stdio.h> 

enum octal_type {AS_INT, AS_UINT}; 

#define fn(x) fn_impl(x, \ 
    _Generic(*x, signed int: AS_INT, unsigned int: AS_UINT, default: AS_INT)) 

void fn_impl(const void *value, enum octal_type type) 
{ 
    switch (type) { 
     case AS_INT: 
      printf("%d\n", *(int *)value); 
      break; 
     case AS_UINT: 
      printf("%u\n", *(unsigned *)value); 
      break; 
    } 
} 

int main(void) 
{ 
    int value = 5; 

    fn(&value); 
    return 0; 
} 
Смежные вопросы