Странное приведение указателя с void *

#c #casting #void-pointers

#c #Кастинг #void-указатели

Вопрос:

Мы работаем над проектом о встроенном Linux с C и C вместе. Недавно я столкнулся со странным оператором в функции:

 bool StrangeFunction(void* arg1, void* arg2, void* arg3)
{
    (void)arg1;
    (void)arg2;
    (void)arg3;

    unsigned long keycode = (unsigned long)arg2;

    switch(keycode)
    {
...
  

У меня есть два вопроса в приведенном выше коде

  1. Что это значит (void)arg1; ?
  2. Возможно ли и можно ли использовать unsigned long keycode = (unsigned long)arg2;

Если вы не возражаете, мне нужны некоторые пояснения и связанные ссылки, объясняющие темы. Спасибо.

Ответ №1:

  1. Это делается для того, чтобы отключить предупреждения компилятора о неиспользуемых параметрах.

  2. Это возможно, но не переносимо. Если на данной платформе адрес соответствует unsigned long , все в порядке. Используйте uintptr_t на платформах, где это доступно, чтобы сделать этот код переносимым.

Комментарии:

1. в GCC 4.8.2, почему вторая строка выдает ошибку? [-fpermissive] Потому что, насколько мне известно, один тип является указателем, а другой не является указателем. Или я что-то упускаю?

2. @FredrickGauss: согласно документу GCC ( gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Option-Summary.html ), -fpermissive является опцией C . Я не знаю о C . Извините.

Ответ №2:

Приведение к void , скорее всего, используется для отключения предупреждений компилятора о неиспользуемых переменных, см. раздел Подавление предупреждений компилятора о неиспользуемых параметрах в C / C :

Вы должны использовать uintptr_t , если это возможно, вместо unsigned long , то есть целочисленный тип без знака, способный содержать указатель. Мы можем видеть из проекта стандартного раздела C99 7.18.1.4 Целочисленные типы, способные содержать указатели на объекты, в котором говорится:

Следующий тип обозначает целочисленный тип без знака со свойством, что любой допустимый указатель на void может быть преобразован в этот тип, а затем преобразован обратно в указатель на void, и результат будет сравниваться с исходным указателем:

uintptr_t

Ответ №3:

Это (void)arg1 ничего не делает, но заставляет компилятор использовать переменную. Это способ иметь функцию, которая принимает параметры, которые не используются, но избегает любых предупреждений компилятора «параметр не используется».

Вторая вещь используется при передаче беззнакового long в функцию, которая принимает a void * . Если вы все равно имеете дело с C , вероятно, лучше иметь перегруженную функцию. Это также имеет недостаток, заключающийся в том, что указатель должен быть по крайней мере таким же большим, как an unsigned long , и поэтому он может не работать на определенных платформах.

Комментарии:

1. также спасибо. Для моего второго случая нас интересует C только и даже если C , мы вообще не можем использовать другую перегруженную функцию.