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()
.