Доступ к указателю переменной как указатель на другой тип в C - PullRequest
0 голосов
/ 18 мая 2019

Это хорошая практика для доступа к переменной указателя путем разыменования указателя на указатель, который указывает на другой тип или void?Может ли это нарушить строгие правила наложения имен?C и C ++ имеют некоторые различия в правилах наложения имен.В этом вопросе мы сосредоточимся на C. Другой вопрос, касающийся C ++, можно найти здесь .В следующем примере к double* обращаются как void*.

int create_buffer(void** ptr, ...)
{
    *ptr = malloc(...);
    ...
}

int main(void)
{
    double* buffer;

    // The problematic code is here, double**
    // is coerced to void**, which is later
    // dereferenced by the function
    create_buffer((void**)&buffer, ...);
    ...
}

Является ли следующее лучше:

// keeping void** just as an indicator in the interface
// that the pointer is pointing to a pointer to any type
// it could be replaced by just void*
int create_buffer(void** ptr, ...)
{
    void* result = malloc(...);
    memcpy((void*)ptr, &result, sizeof result);
}

Ответы [ 2 ]

0 голосов
/ 18 мая 2019

Я бы лучше написал это так, предполагая, что вы используете "int", чтобы вернуть вызывающей стороне некоторую полезную информацию, без которой он не может обойтись:

void *create_buffer(size_t n, int *otherInfo) {
    void *ptr = malloc(n);
    *otherInfo = 0;
    if (ptr) {
        // Do whatever other initialization is expected
        // memset(ptr, 0, n);
    } else {
        *otherInfo = -1;
    }
    return ptr;
}

int main(void)
{
    double* buffer;
    int code;

    /* cast is not required by language or compiler, 
       but I still find it useful when reading */
    buffer = (double *)create_buffer(SIZE_REQUIRED, &code);

    /* equality testing can be done either way. This way here,
       if you ever forget a =, will never compile anywhere. Nowadays
       many compilers are smart enough to catch it on their own anyway */
    if (NULL == buffer) {
        // Handle out of memory error or other problem
        switch(code) {
            case -1:
                fprintf(stderr, "Out of memory\n");
            ...
            default:
                fprintf(stderr, "Unexpected error %d\n", code);            
                break;
        }
    }
}
0 голосов
/ 18 мая 2019

Не отвечая на ваш вопрос, но вы можете маневрировать вокруг неопределенностей, о которых вы упомянули, просто выполняя четко определенные вещи, такие как:

int main(void)
{
  double* buffer;

  {
    void * pv;
    create_buffer(&pv, ...);
    buffer = pv; /* C does not need any cast here. */
  }

  ...
...