Задать вопрос
ali_aliev
@ali_aliev
Разработчик на Django/Python, JavaScript

Странное поведение массивов в Си

Потихоньку начинаю вникать в Си. К сожалению я далек от низкоуровневого программирования, поэтому перейду сразу к глупому вопросу.

Имеем массив:
#include <stdio.h>

int main(int argc, char *argv[]) {
    char *name = "Hello World";
    printf("%p", &name);
    printf("%p", name);
    printf("%s", name);
}


Почему первый и второй принт выдает адрес первого элемента в массиве и при этом во время обращении к name возвращается вся строка да и еще sizeof(name) возвращает размер всей строки в массиве? Есть еще один вопрос по поводу массивов: элемент массива можно получить вот так (то есть работать с ними как с указателями) *(name + 1), получается что сами по себе массивы являются указателями? Где об этом можно подробнее прочитать?

P.S. Зачем нужны указатели на указатели?

Заранее, благодарю.
  • Вопрос задан
  • 3896 просмотров
Подписаться 5 Оценить Комментировать
Решение пользователя ntkt К ответам на вопрос (7)
ntkt
@ntkt
Потомственный рыцарь клавиатуры и паяльника
Массив как переменная в C — это псевдоним адреса в памяти, по которому лежит его первый элемент.
Массива ни в машинном коде, ни в памяти, строго говоря, не существует. Существует только его «содержимое» — его элементы.
При обращении к элементу массива действия производятся машиной прямо над его содержимым по вычисленному адресу.
Самого массива — не существует.
Всякий раз, когда в С Вы работаете с массивом — компилятор использует или указатель на первый элемент массива (например, когда Вы передаете массив в функцию), или адрес первого элемента массива, а машина далее с этим работает.

Указатель в C — это переменная, содержащая адрес в памяти.
Указатель в машинном коде и памяти — существует. Он имеет значение — число размером с разрядность машины, а значение числа — это адрес в памяти.
Указатель как число — может быть передан в регистрах, лежать на стеке, и т.д.
При обращении к байту/слову/двойному слову/… по смещению через указатель, в машинном коде указатель разыменовывается (в явном виде берется его значение=адрес) т.е. в машинном коде происходят несколько другие действия, чем в случае для массива.

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

Вот, кстати, приличное описание различий на английском:
eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/
Ответ написан
Комментировать