Определить знак параметра неоднозначного указателя для функции - PullRequest
0 голосов
/ 17 октября 2018

Можно ли определить параметр неоднозначного указателя знака для функции в C и / или C ++?

Например, скажем, у меня есть функция, которая работает как с 8-битным типом без знака, так и со знаком.переменная, и функция получает указатель на переменную, которая будет обработана / обработана.

Я знаю, что могу выполнить тип с (unsigned char *) или (signature char *), но я ищу что-то более чистое.

unsigned char Var1;
signed char Var2;

void MyFunction(unsigned char* Var);

MyFunction(&Var2); // This creates an error

С учетом сказанного я хотел бы поднять мысль о том, что языки выше, чем сборка, не должны использовать имена, такие как BYTE / WORD / DWORD или QWORD, для определения переменной с явным типом знака.Я говорю это потому, что это операторы размера для сборки и на самом деле не определяют знак.Знак в сборке выбирается по выбранной инструкции.Тем не менее, я вижу, что эти имена используются повсеместно в C / C ++ и определены как незапятнанные, по крайней мере в Windows.Это похоже на конфликт интересов для меня ...

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

С C у вас есть ограниченные возможности.При вызове функции вы можете выполнять приведение типов, которое вам не нравится:

void MyFunction(unsigned char* Var);

int main(void) {
    unsigned char Var1 = 5U;
    signed char Var2 = 5;

    MyFunction(&Var1);
    MyFunction((unsigned char *)&Var2);
}

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

void MyFunction(void* Var);

int main(void) {
    unsigned char Var1 = 5U;
    signed char Var2 = 5;

    MyFunction(&Var1);
    MyFunction(&Var2);
}

Или, если вы действительно хотите чего-то сверх этого, вы можете использовать макрос _Generic, чтобы автоматически настроить его для вас.Это может быть или не быть «лучшим» подходом, но я думаю, что он достигнет вашей цели.

#define MY_FUNCTION_HELPER(X) MyFunction( _Generic((X), \
   char *: (unsigned char *)X, \
   signed char *: (unsigned char *)X, \
   unsigned char *: X \
   ) \
)

void MyFunction(unsigned char *Var);

int main(void) {
    unsigned char Var1 = 5U;
    signed char Var2 = 5;

    MY_FUNCTION_HELPER(&Var1);
    MY_FUNCTION_HELPER(&Var2);
}

Последний работает с использованием введенного C11 _Generic, который позволяет форме полиморфизмаиспользовать разные выражения в зависимости от типа управляющего выражения.В этом случае, если X равно char * или signed char *, он выполнит приведение типа к unsigned char *.Если X уже unsigned char *, оно останется таковым.Если X - это что-то еще, он не сможет скомпилироваться, так как никакие другие типы не учитываются в общем списке ассоциаций.

0 голосов
/ 17 октября 2018

Если логика для двух типов объектов одинакова, лучше всего использовать шаблон функции.

template <typename T>
void MyFunction(T* Var);

Если вы хотите ограничить использование функции только для 8-битныхтипы, вы можете использовать static_assert в реализации.

template <typename T>
void MyFunction(T* Var)
{
   static_assert(sizeof(T) == 1, "Wrong type. Can only deal with 8-bit types.");
   ...
}
...