Доступ к многомерным массивам осуществляется через временные указатели? - PullRequest
0 голосов
/ 29 января 2019

Я читал, что доступ к индексам массива такой же, как доступ к индексам (не удается найти правильную ссылку, но http://c -faq.com / aryptr / joke.html упоминает, что косвенно).

Так что насчет многомерного доступа?Очевидно, что нет указателя на c [0] в многомерном массиве.

#include <stdio.h>

int main(){
    char c[5][2][4];
    c[1][1][2] = 'n';
    printf("\n%c", c[1][1][2]);
    char* ptr = c;
    printf("\n%c\n", ptr[1*8+4*1+2]);
}

Но все, на что он ссылается (в трехмерном массиве [d1] [d2] [d3]), имеет размер d2 * d3, так как именно здесь смещается воображаемый указатель.

Есть ли какие-либо документы о том, как это реализовано или как это можно обосновать?В двумерном случае имеет смысл, что это просто указатель, но для случая 3+ неясно, работают ли / как с указателями все еще.

Ответы [ 3 ]

0 голосов
/ 29 января 2019

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

Я подчеркиваю «yield», чтобы развеять мысль о том, что массив на самом деле является указателем - это не так.Механизм часто описывается как «распадается на указатель», что лично меня вводит в заблуждение;в конце концов, сам массив остается неизменным.

Итак, да, вы можете рассуждать об этом, как будто доступ к массиву создает временный указатель.

0 голосов
/ 29 января 2019

Концепция объясняется здесь: С массивами, почему так получается, что [5] == 5 [a]? .Это альтернативный синтаксис, допускаемый «случайно» для сохранения согласованности языка, и ничего более.

Это не имеет ничего общего с типом контейнера, вы можете делать такие же неясные трюки с указателем на указатель, как с многомерными массивами.Пример:

#include <stdio.h>

int main (void)
{
  char str[2][2][6] =
  {
    {"hello", "world"},
    {"foo",   "bar"}
  };

  printf("%c\n", str[0][0][0]); // print h
  printf("%c\n", 0[0[0[str]]]); // print h  (bad code, don't do this)
}

Причина, по которой вы можете делать такие вещи, как ptr[1*8+4*1+2], - это другая история, а именно то, что многомерный массив гарантированно размещается непрерывно.Это указано в C17 6.2.5 / 20:

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

Что касается «мнимых указателей», то, как получить доступ к массиву в машинном коде, зависит от компилятора.Иногда эффективнее использовать прямые адреса, иногда он использует базовый адрес + смещение.Это тот тип автоматической оптимизации, о котором программистам не нужно беспокоиться.

0 голосов
/ 29 января 2019

Кажется, вам не нужно слышать разоблачение лжи "массивы - замаскированные указатели".Поэтому я не буду повторять это.Но достаточно сказать, что да, вся индексация происходит через указатели.Когда вы пишете c[0], c распадается на указатель с целью индексации *(c + 0).

Но указатель на то, что вы спрашиваете?Конечно, указатель на массив.Вы можете сформировать их.Например:

char d[2][4];
char (*ptr)[2][4] = &d;

Здесь ptr указывает на этот массив типа char[2][4].И это именно тот вид указателя, в который распадается c.Вот почему школа многомерного мышления в C не слишком точна.У нас нет тех, что у нас есть массивы из массивов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...