2015-06-10 3 views
3

Известно, что имена массивов распадаются на указатель, такой как a[i], эквивалент *(a+i). Я наткнулся на вопрос, задавая мне предсказать результат:Array Syntax Confusion

int main(void) 
{ 
    printf("%c", "abcdefgh"[4]); 
    return 0; 
} 

ответ, который они говорят, e и причина, которую них, как a[4] преобразуется в *(a+4) где a является базовый адрес массива a на подобных линиях мы может найти результат вышеупомянутого вопроса.

Но как я не понимаю, как с a[i] разлагающихся в *(a+i) потому компилятор обрабатывает это тот путь, но в фрагменте кода выше, как и почему мы будем рассматривать "abcdef"[4] это?

ответ

4

Вы будете удивляться еще больше, если я скажу, что вы можете написать даже следующий образ :)

printf("%c\n", 4["abcdefgh"]); 

строковых литералов в C имеют типов символьных массивов. Таким образом, строковый литерал «abcdefgh» имеет тип char[9]. Он включает также завершающий нуль.

В выражениях массивов, как вы правильно упоминали разложение указателей на их первые элементы. Так что строка буквенные затухает до указателя типа char *, который указывает на первый символ буквального, который должен 'a'

Согласно стандарту C (6.5.2.1 индексацией массивов)

2 Выражение постфикса с последующим выражением в квадратных скобках [] - это индексированное обозначение элемента объекта массива. определение индекса оператора [] состоит в том, что E1[E2] идентичен (*((E1)+(E2))).Из-за правило преобразования, которые применяются к двоичному + оператору , если E1 является объект массива (что эквивалентно, указатель к исходному элементу объекта массива) и E2 представляет собой целое число, E1[E2] обозначает E2-й элемента E1 (с нуля).

Таким образом, это выражение (*((E1)+(E2))) не зависит от того, начальная запись была E1[E2] или E2[E1]

Возвращаясь к коду shippet у вас есть, что в этом выражении

4["abcdefgh"] 

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

char *p = "abcdefgh"; 

и вы получите

4[p] эквивалентно *(4 + p) и приводит Lvalue характера 'e'

3

"abcdefgh"[4] равнозначно *("abcdefgh" + 4). При использовании в выражении (кроме случаев, когда это операнд унарного оператора & и sizeof) "abcdefgh" представляет собой базовый адрес строки.

В общем, помните, что можно использовать строковый литерал, где разрешен указатель char *. В сниппета

char *ptr; 
p = "abcdefgh"; 

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

char ch; 
ch = "abcdefgh"[4]; 
+2

«При использовании в выражении» - нет, не в любом выражении, только если это не операнд операторов 'sizeof' или' & '. –

+0

@ TheParamagneticCroissant; Да. Отредактировал это. – haccks

0

"abcdefgh" является массивом. Это массив символов, аналогичных (но не идентичных) как если бы вы объявили переменную типа char[9] и длительности static хранения:

static char str[9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0 }; 

Таким образом, вы можете индексироваться так же, как любой другой массив, используя [] индексный оператор.