Являются ли указатели и массивы разными в C?

Я пишу небольшую программу на C, чтобы сделать хруст, и мне нужно передать массивы между функциями. Функции должны принимать и возвращать указатели, правильно?

Например, это (я знаю, что это не самая эффективная вещь):

int* reverse(int* l, int len) {
    int* reversed = malloc(sizeof(*reversed)*len);
    int i, j;
    for (i = 0, j = len-1; i < len; i++, j--) {
        reversed[j] = l[i];
    }
    return reversed;
}

Я правильно использую указатели?

Ответы

Ответ 1

Ваш фрагмент кода верен. Однако указатели и массивы в C действительно разные. Проще говоря, "указатель на тип T" не такой же, как "массив типа T".

Пожалуйста, посмотрите C Faq, обсуждая указатели и массивы, чтобы лучше понять это.

Ответ 2

Ссылка на C-FAQ: Массивы и указатели уже предоставлены, но есть также подробное объяснение в C для Smarties: Массивы и указатели. Сначала вы можете прочитать страницу "Анализ выражений".

Несколько вещей о вашем примере, которые следует исправить:

  • Использование int вместо правильного size_t для хранения размеров объектов.
  • Невозможно проверить возвращаемое значение malloc().

Один из способов "исправить" эту вторую проблему - позволить вызывающему абоненту решить, где хранится вывод (возможно, вызывающему не нужен или нужен только что выделенный массив):

int *reverse(int *out, int *l, size_t len) {
   size_t i, j;
   for (i = 0, j = len - 1; i < len; ++i, --j) {
     out[j] = l[i];
   }
   return out;
 }

Ответ 3

С точки зрения низкого уровня массив представляет собой непрерывный кусок памяти, к которому обращается адрес начала этого фрагмента и смещения, поэтому из этого уровня абстракции это указатель. Однако, с точки зрения языка C, тип массива отличается от типа указателя. В основном массив может быть назначен на значение указателя, но он не тот же тип.

В целях вашей функции вы все в порядке.

Ответ 4

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

На практике они одинаковы, так как формально a[i] - это то же самое, что и *(a+i), и поэтому конец компилятора обрабатывает имя массива и указатель точно так же. Единственное различие, о котором стоит беспокоиться, заключается в том, что

void foo()
{
   int a[5]; // allocates five words of space on the stack
   int *b;   // allocates *one* word of space on the stack (to hold the pointer)
}

Ваш фрагмент кода в порядке. Просто будьте осторожны, чтобы освободить память, чтобы ваша функция malloc() была в том, кто ее называет.

Ответ 5

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

int arr[50];
int * ptr1 = arr;
int * ptr2 = &arr[0];

в этом примере, ptr1 == ptr2, потому что адрес первого элемента массива и базовый указатель для массива одинаков.

, поэтому ваш основной пример правильный, хотя я подозреваю, что malloc должен быть:

int* reversed = malloc(sizeof(int)*len);

Забастовкa >