Что плавает * a [];объявить в с? - PullRequest
0 голосов
/ 31 мая 2019

Предположим, float * a [];объявлен в основном методе n c.Я пытаюсь узнать об указателях и понять, что означает это выше.

Я предполагаю, что он объявляет указатель на первый элемент этого массива a [].Но у [] нет элементов ... Я действительно запутался.

Спасибо всем, кто помогает.

Ответы [ 3 ]

6 голосов
/ 31 мая 2019

При объявлении переменной недопустимый код без размера массива.

a.c: In function ‘main’:
a.c:2:11: error: array size missing in ‘a’
    float *a[];

При размере массива создается массив указателей.

Test:

#include <stdio.h>

int main() {
   printf("float:           %zu\n", sizeof(float));
   printf("pointer:         %zu\n", sizeof(void*));

   float *a[100];
   printf("float *a[100]:   %zu\n", sizeof(a));

   float (*b)[100];
   printf("float (*b)[100]: %zu\n", sizeof(b));
   printf("*b:              %zu\n", sizeof(*b));

   return 0;
}

Вывод:

float:           4
pointer:         8
float* a[100]:   800       // a is an array of 100 float pointers.
float (*b)[100]: 8         // b is a pointer to an array of 100 floats.
*b:              400

Обратите внимание, что в C есть особый случай, когда [] объявляет не массив, а указатель.При объявлении параметра функции:

void f(float *a[], size_t n) {
   // ...
}

[] обрабатывается как объявление указателя, поэтому оно эквивалентно:

void f(float **a, size_t n) { // ...

Поскольку массив распадается на указатель на свой первыйэлемент при передаче его в качестве аргумента функции, функция может принимать массивы:

int main() {
   int n = 100;
   float *a[n];
   // ... Initialize the array here ...
   f(a, n);
   return 0;
}

Это причуды языка Си.

4 голосов
/ 31 мая 2019

Можно указать пустой размер массива, если компилятору не нужно знать размер массива.

Это имеет место в двух ситуациях:

  • extern декларации
  • типы аргументов функции

Пример 1:

extern float *a[];

Используя строку выше, вы сообщаете компилятору C, что в некотором файле C есть массив float * элементов с именем a.

Пример 2:

void someFunction(float *a[])

Используя эту строку, вы указываете, что тип аргумента является массивом float * элементов.

Оба будут работать, потому что компилятору не нужно знать размер массива для доступа к нему. Компилятору нужно знать только размер, чтобы зарезервировать память для массива.

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

1 голос
/ 31 мая 2019
float *a[];

является неполным объявлением массива указателей на float, поскольку он не имеет размера.В какой-то момент также должно быть определяющее объявление, которое указывает число элементов, либо явно, либо с использованием инициализатора:

float *a[];
...
float *a[N];

или

float *a[];
...
float *a[] = {&a, &b, &c, ...};  // where a, b, c, ..., are objects of type float

В качестве члена *Тип 1011 *, например

struct foo {
  int something;
  int something_else;
  float *a[];
};

это гибкий элемент массива - если вы просто объявляете экземпляр struct foo как

struct foo bar;

, тогда это нене является частью объекта (вы не можете получить доступ bar.a[i]).Однако, если вы выделяете объект динамически, вы можете указать дополнительное пространство для массива:

struct foo *p = malloc( sizeof *p + sizeof *(p->a) * N );

, что эквивалентно определению типа структуры как

struct foo { 
  int something;
  int something_else;
  float *a[N];
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...