Как правильно передавать указатели на массивы в C? - PullRequest
2 голосов
/ 26 мая 2020

Возьмите этот фрагмент кода в качестве примера:

#include <stdio.h>
void print_array(size_t size, unsigned (*myarray)[])
{
    printf("Array size: %lu\n", size);
    for (size_t i = 0; i < size; ++i)
            printf("%u ", (*myarray)[i]);
    printf("\n");
}
int main() {
    unsigned myarray[] = { 9, 8, 7, 6, 5 };
    print_array(sizeof(myarray) / sizeof(unsigned), &myarray);
    return 0;
}

При компиляции с помощью анализатора clang (через g cc 10.1.0) предупреждение будет следующим:

src/main.c:7:3: warning: 2nd function call argument is an uninitialized value
            printf("%u ", (*myarray)[i]);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

вывод:

Array size: 5
9 8 7 6 5 

В чем ошибка в этом фрагменте кода и как правильно передавать указатели на массивы в C?

Ответы [ 2 ]

2 голосов
/ 26 мая 2020

Это похоже на ложное срабатывание. С кодом проблем нет - хотя стиль немного экзотичен c, он все действителен C.

Если замечание касается фактического отсутствия инициализации, это может быть связано с инструментом, который не проверка звонящего. Но даже если анализатор принимает во внимание только локальную единицу трансляции, он не может go выключить и предположить, что переданные переменные по умолчанию не инициализированы. Это было бы очень странное предположение.

Возможно, анализатор испугался, что вы на самом деле передаете unsigned (*myarray)[5] функции, ожидающей unsigned (*myarray)[] (указатель на неполный тип, массив неопределенного размера). Вы можете попробовать изменить параметр на unsigned (*myarray)[size]) и посмотреть, улучшит ли это работу инструмент.

Изменить: типы указателей на массивы совместимы, поэтому инструмент не должен жаловаться и по этой причине. Согласно C17 6.7.6.2/6, один или оба типа массива могут не указывать спецификатор размера и по-прежнему быть совместимыми:

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

2 голосов
/ 26 мая 2020

Вы можете просто передать указатель и использовать тот факт, что переменные массива представляют адрес, с которого начинается их первый элемент. Похоже, что использование pedanti c с clang делает множество предположений о том, на что может указывать аргумент функции, поэтому он жалуется.

void print_array(size_t size, const unsigned *myarray)
{
    printf("Array size: %lu\n", size);
    for (size_t i = 0; i < size; ++i)
            printf("%u ", myarray[i]);
    printf("\n");
}

int main() {
    unsigned myarray[] = { 9, 8, 7, 6, 5 };
    print_array(sizeof(myarray) / sizeof(unsigned), myarray);
    return 0;
}
...