Понимание синтаксиса указателей манипулирования массивом в C - PullRequest
5 голосов
/ 10 февраля 2020

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

void main(void)
{
  char arr[][10] = {"It's", "wide", "and", "wonderful"};
  printf("%c", (*arr)[3] - 1);
  printf("%c", *arr[2] + 3);
}

Я понятия не имею, почему он печатает 'r' и 'd' как весь процесс Я хотел бы получить объяснение.

Ответы [ 8 ]

5 голосов
/ 10 февраля 2020

Это запутывание: код, преднамеренно написанный, чтобы запутать.

*arr дает первый элемент (массив) в вашем 2D-массиве. В индексе 3 вы найдете 's'. Код ASCII для 's' - 1 = 'r'.

В *arr[2] оператор [] имеет приоритет, давая вам элемент с индексом 2 в вашем двумерном массиве («и»). * дает содержимое первого элемента (символа) в этом массиве, 'a'. Код ASCII для 'a' + 3 = 'd'.

(Обратите внимание, что арифметическое c для значений таблицы символов не является переносимым кодом. Стандарт * C гарантирует только цифры от 0 до 9 для размещения рядом в таблице символов.)

2 голосов
/ 10 февраля 2020

Выражение *arr[2] эквивалентно 1), 2) до arr[2][0] -

*arr[2] -> *(arr[2]) -> *((arr[2]) + 0) -> arr[2][0]

Выражение (*arr)[3] эквивалентно 2) arr[0][3] -

(*arr)[3] -> (*(arr + 0))[3] -> arr[0][3]

arr[0][3] представляет 3 rd символ в первом массиве, который равен s, а arr[2][0] представляет 0 th символ в третий массив a

2D массив arr:

Array arr:
  [0] = {
    [0] = 'I'
    [1] = 't'
    [2] = '''
    [3] = 's'   ---> (*arr)[3], substrat 1 from s ==> r
    [4] = '\0'
    [5] = '\0'
    [6] = '\0'
    [7] = '\0'
    [8] = '\0'
    [9] = '\0'
  }
  [1] = {
    [0] = 'w'
    [1] = 'i'
    [2] = 'd'
    [3] = 'e'
    [4] = '\0'
    [5] = '\0'
    [6] = '\0'
    [7] = '\0'
    [8] = '\0'
    [9] = '\0'
  }
  [2] = {
    [0] = 'a' --> *arr[2], add 3 to a ===> d
    [1] = 'n'
    [2] = 'd'
    [3] = '\0'
    [4] = '\0'
    [5] = '\0'
    [6] = '\0'
    [7] = '\0'
    [8] = '\0'
    [9] = '\0'
  }
  [3] = {
    [0] = 'w'
    [1] = 'o'
    [2] = 'n'
    [3] = 'd'
    [4] = 'e'
    [5] = 'r'
    [6] = 'f'
    [7] = 'u'
    [8] = 'l'
    [9] = '\0'
  }
}

1) Приоритет оператора [] выше, чем унарный оператор *.

2) C Стандарты # 6.5.2.1

Определение оператора индекса [] состоит в том, что E1 [E2] идентично (* ((E1) + ( E2))) ..

2 голосов
/ 10 февраля 2020

Я разобью выражения (*arr)[3] - 1 и *arr[2] + 3 в порядке старшинства.

Выражение (*arr)[3] - 1:

  • arr{"It's", "wide", "and", "wonderful"}
  • (*arr)"It's"
  • (*arr)[3]'s'
  • (*arr)[3] - 1'r'

Обратите внимание, здесь два вещи: *arr эквивалентно arr[0], и вы можете выполнить арифметику c для char, оперируя значением цифра c, представляющим символ.

Выражение *arr[2] + 3:

  • arr{"It's", "wide", "and", "wonderful"}
  • arr[2]"and"
  • *arr[2]'a'
  • *arr[2] + 3'd'

Новость заключается в том, что arr[] имеет приоритет над *arr, поэтому скобки важны в первом выражении.

2 голосов
/ 10 февраля 2020

Для (*arr)[3] - 1:

  • arr, если рассматривать как указатель: адрес первого элемента. В данном случае это адрес "It's"
  • (*arr): разыменование arr, он же "This". И это char*
  • (*arr)[3]: четвертый символ «Это». Типом является char
  • (*arr)[3] - 1: char может использоваться как целое число, поэтому вычитание char вычитает его ASCII-код . Значение 'r'

Для *arr[2] + 3:

  • arr[2]: 3-й элемент arr (рассматривается как массив), который является "and". Тип: char*
  • *arr[2]: разыменование "and", поэтому 'a'
  • *arr[2] + 3: снова код ASCII, его значение 'd'
2 голосов
/ 10 февраля 2020

Массивы, используемые в выражении, неявно преобразуются (за редкими исключениями) в указатели на их первые элементы.

Так что, если массив объявлен так

char arr[4][10]

, то это объявление вы можете переписать как

char ( arr[4] )[10]

и в выражении указатель массива преобразуется в указатель на его первый элемент

char ( *p )[10]

Так что в этом выражении

(*arr)[3] - 1)

преобразовывается arr на тип char ( * )[10] и указывает на первую строку, хранящуюся в массиве. Применяя оператор *, вы получаете первый подмассив (первую строку), который имеет тип char[10].

. Применяя оператор индекса, вы получаете четвертый символ в строке, равный 's' , Теперь вычитая 1, вы получите символ 'r'.

Во втором выражении

*arr[2] + 3

, которое можно эквивалентно переписать, например

*( arr[2] ) + 3

, которое вы сначала получите третий подмассив массива, который является подмассивом со строкой "и" . This sub-array has the type char [10] . Dereferencing the array designator (that is implicitly converted to pointer to its first element) you get the first character of the string that is 'a' Adding to the character 3 you get the character 'd'`.

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

Вы должны понимать, что если у вас есть такой массив, как например,

char s[] = "Hello";

, тогда выражение *s эквивалентно *( &s[0] ), то есть s[0].

2 голосов
/ 10 февраля 2020

Во-первых, отметим, что *arr[2] эквивалентно *( arr[2] )

Во-вторых, имейте в виду, что между *(a + i) и a[i].

нет разницы. В-третьих, если нет никакой разницы между *(a + i) и a[i], нет никакой разницы между *a и a[0].

Итак,

(*arr)[3]   ===   ( *( arr + 0 ) )[3]   ===   arr[0][3]

Выше приведен четвертый символ первого строка.

*arr[2]   ===   *( arr[2] )   ===   *( arr[2] + 0 )   ===   arr[2][0]

Выше приведен первый символ третьей строки.

2 голосов
/ 10 февраля 2020

в первом случае (*arr)[3] - 1

  • (* arr) дает нам указатель на первый элемент массива: "It's"
  • (* arr) [3] дает нам Четвертый элемент «Это», который: 's'
  • вычитая 1 из 's', дает нам 'r'

во втором случае *arr[2]:

  • arr [2] дает нам указатель на третий элемент массива: "и"
  • * arr [2] дает нам первый символ "and", который является 'a'
  • добавление 3 к «а» дает нам «d»
2 голосов
/ 10 февраля 2020
void main(void)
{
  char arr[][10] = {"It's", "wide", "and", "wonderful"};
  printf("%c", (*arr)[3] - 1); // arr[0][3] == the 4th char of the 1st string - 1 = s - 1 = r
  printf("%c", *arr[2] + 3); // arr[2][0] == the 1st char of the 3rd string + 3 = a + 3 = d
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...