Typedef неограниченный float-массив в C

я сделал typedef для float-массивов, например:

typedef float fooType[];

чтобы я мог объявлять и инициализировать массивы float статически следующим образом:

fooType myArray = {1.0, 2.0, 3.0}

это прекрасно работает. Я могу сказать myArray[2] без проблем и вообще использовать мой fooType как я хотел бы. В контексте моей программы очень ясно, что fooType является типом массива (это на самом деле гигантская таблица поиска), поэтому я не просто делаю typedef float fooType.

как мне объявить и использовать переменная, указывающая на bar и получить доступ к элементам bar? Я не могу объявить такую простую переменную:

fooType bar = myArray;

так как это ошибки с invalid initializer, я не ожидал его на работу, поскольку компилятор не знает сколько памяти выделить. Я попробовал несколько вещей с указателями:

fooType *bar = myArray; 

это дает предупреждение: initialization from incompatible pointer type и ошибки при доступе к элементам с bar[1].. Это объявляет отлично, как я и ожидал, так как типы совпадают теперь:

fooType *bar = &myArray;

но, как и выше, ошибки компилятора с invalid use of array with unspecified bounds когда я говорю bar[1].

это работает:

float *bar = myArray; 
float val = bar[3]; 

но я не хочу, потому что я теряю читаемость моего typedef.

я был похоронен в течение длительного времени в приятном мире OO (Java), поэтому я надеюсь понять из этого, что идиоматично в C в этой ситуации. Я вполне готов изменить свое использование typedef в соответствии с Конвенцией, если нет прямого решения. У меня есть но чувство есть, и оно несложное.

спасибо

3 ответов


проблема, с которой вы сталкиваетесь здесь, заключается в том, что массивы не являются указателями в C, а скорее распадаются на указатели на первый элемент при использовании в правой части оператора присваивания. Таким образом, если вы объявляете массив как

fooType myArray = {1.0, 2.0, 3.0}

тип myArray is float[3], и & myArray является (*float)[3], или "указатель на массив из 3 поплавков". Таким образом, вы не можете просто сказать

fooType *bar = myArray;

тип fooType* не является указателем на поплавок ... таким образом, это несовместимый тип указателя. Делать

fooType* bar = &myArray;

работает, но проблема, с которой вы сталкиваетесь, заключается в том, что bar[1] не является элементом в массиве myArray С bar сам по себе является указателем. Вам придется разыгратьbar как (*bar)[1] для доступа к элементу в myArray. Например:

typedef float fooType[];
fooType myArray = {1.0, 2.0, 3.0}
fooType* bar = &myArray;
(*bar)[1] = 5.0;

наконец, имейте в виду, что с помощью C вы не можете назначить один массив другому массиву ... так что вы можете сделать что-то вроде:

fooType bar = myArray;

это восходит ко всему вопросу массивов и их распада на указатели на первый элемент, и тому, что тип самого массива не совпадает с типом первого элемента в массиве.

вы можете в конце концов просто захотеть typedef массив, а затем typedef типы элементов массива с помощью float чтобы любой, кто использует ваш код, знал, какой тип элемента принадлежит другому.


вы смешали C С Java.

попробуйте изменить свой typedef на

typedef float *fooType;

после этого, однако вы не сможете инициализировать переменную типа fooType как

fooType myArray = {1.0, 2.0, 3.0};

, потому что fooType теперь указатель.


используя Visual Studio 2013, я обнаружил, что вы можете использовать конструкции, такие как в этом примере. Это также работает с Visual Studio 2015.

обратите внимание, что использование malloc() для создания массива fooType требуется разыменованный указатель типа pfooType а не типа fooType или *pfooType для компиляции. Я изменил typedef С float to double и sizeof(*p2) изменено с 4 до 8 байт, как ожидалось.

#include <malloc.h>

typedef float fooType[], *pfooType;

int xxmain2(void)
{
    fooType myArray = { 1.0, 2.0, 3.0 };   // define the array with its elements
    pfooType p = myArray;   // get a pointer to the array.
    int i;
    int  nElements = sizeof(myArray) / sizeof(*p);  // determine number of elements in the array.

    pfooType p2 = malloc(sizeof(*p2) * 5);  // malloc() an array of 5 elements.

    for (i = 0; i < 5; i++) p2[i] = (float)i * 10.0;  // initialize my malloced array.
    myArray[0] = *p;       // dereference pointer
    myArray[1] = p[1];     // use array subscripting with pointer

    for (i = 0, p = myArray; i < nElements; i++) *p++ = 0;   // increment the pointer to traverse the array.

    free(p2);
    return 0;
}

я также обнаружил, что могу не создавайте заданный размер массива с чем-то вроде fooType myRay2[10]; (ошибка компиляции " error C2087:' myRay2': missing subscript") или что-то подобное. И fooType myRay2; дает ошибку компиляции " ошибка C2133:' myRay2': неизвестный размер".

таким образом, единственный способ - использовать инициализацию для размера массива или использовать malloc() чтобы создать массив определенного размера, который затем требует free().