1) Указатели не являются массивами. Массивы не являются указателями. Не думайте о них так, потому что они разные. Как я могу это доказать? Подумайте, как они выглядят в памяти:
Наш массив arr
имеет длину 10 символов. Он содержит «Привет», но подождите, это еще не все! Поскольку у нас есть статически объявленный массив дольше, чем наше сообщение, мы получаем кучу NULL символов ('\0'
), брошенных бесплатно! Также обратите внимание на то, что имя arr
концептуально привязано к смежным символам (оно не указывает ни на что). [/g0]
Далее рассмотрим, как наш указатель будет выглядеть в памяти: [/g1] Обратите внимание, что мы указываем на массив символов в некотором месте в памяти только для чтения.
Таким образом, хотя оба arr
и ptr
были инициализированы одинаково, содержимое / местоположение каждого на самом деле различно.
Это ключевой момент: ptr - это переменная, мы можем указать ее на что угодно, arr - константа, она всегда будет ссылаться на этот блок из 10 символов.
2) []
является оператором «add and deference», который может использоваться по адресу. Это означает, что arr[0]
совпадает с *(arr+0)
. Итак, да, сделайте это:
printf("%c %c", *(arr+1), *(ptr+1));
Дает вам вывод «e e». Это не потому, что массивы являются указателями, потому что имя массива arr
и указатель ptr
оба передают вам адрес.
Ключевой пункт для # 2: Оператор deference *
и оператор add и deference []
не относятся к указателям и массивам соответственно. Эти операторы просто работают с адресами.
3) У меня нет очень простого ответа ... поэтому давайте забудем наши массивы символов на секунду и рассмотрим этот пример для Объяснение:
int b; //this is integer type
&b; //this is the address of the int b, right?
int c[]; //this is the array of ints
&c; //this would be the address of the array, right?
Итак, это довольно понятно, как об этом:
*c; //that's the first element in the array
Что говорит вам эта строка кода? Если я уважаю c
, тогда получаю int. Это означает, что просто c
- это адрес. Поскольку это начало массива, это адрес массива, а также адрес первого элемента в массиве, таким образом, с точки зрения значения:
c == &c;
4) Позвольте мне уйти тема для второго здесь ... этот последний вопрос является частью путаницы адресной арифметики. В какой-то момент я увидел вопрос о SO, подразумевающий, что адреса - это целые значения ... Вам нужно понять, что в адресах C есть знание типа. То есть:
iarr+1; //We added 1 to the address, so we moved 4 bytes
arr+1; //we added 1 to the address, so we moved 1 byte
В основном sizeof(int)
равно 4, а sizeof(char)
равно 1. Таким образом, «добавление 1 к массиву» не так просто, как кажется.
Итак, вернемся к вопросу, почему arr+1
отличается от &arr+1
? Первый добавляет 1 * sizeof(char)
= 1 к адресу, второй добавляет 1 * sizeof(arr)
= 10 к адресу.
Вот почему, хотя они оба «добавляют только 1», они дают разные результаты.