безопасное приведение в C

#c #casting

#c #Кастинг

Вопрос:

всем привет, у меня есть этот фрагмент кода:

 void writer(void* param){
    if(NULL == param){
        return;
    }
    param = (param_t*)param;
...
}
  

это безопасный код или нет, параметр имеет тип param_t *, но мне надоело выполнять каждый раз приведение, когда я использую его в функции, у кого-нибудь есть другое элегантное решение? заранее спасибо

Ответ №1:

Это странный сбой.

Когда вы определяете функцию, вы говорите, что параметр имеет тип void* .
Затем с помощью приведения вы явно преобразуете его в param_t*
И компилятор неявно преобразует это param_t* в void* с присваиванием.

Вам нужна другая переменная

 void writer(void *param) {
    param_t *internal_param;

    if (NULL == param) return;
    internal_param = param;
    /* ... */
}
  

Ответ №2:

Вам не нужно приводить значение void * к другому типу указателя в C.

Так что просто сделайте:

 void writer(void* param){
   param_t *myparam;
    if(NULL == param){
        return;
    }
    myparam = param;
...
}
  

(Но почему вы все равно используете void * для аргумента?)

Ответ №3:

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

 void writer(void* param)
{
  param_t* myparam = param;

  if (myparam == NULL)
    return;

  ...
}
  

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

1. Я бы просто использовал «преобразование» (возможно, с «неявным») там: «приведение» — это «явное преобразование» 🙂

Ответ №4:

Очевидное решение — избегать использования void * и использовать param_t * вместо этого, как в:

 void writer(param_t * param)
{
  if (param == NULL)
  {
    return;
  }

  ...
}
  

Вы могли бы отказаться от нулевого теста, если знаете, что он никогда не вызывается с нулевым указателем. В качестве альтернативы вы могли бы заменить его на assert(param != NULL) .

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

1. Я подозреваю, что OP следует требуемой сигнатуре функции для некоторого API, например, для функции запуска потока. Таким образом, изменение типа аргумента невозможно.