Электроника и радиотехника => Цифровая техника => Тема начата: Nikopol от 17 Июль, 2020, 13:27
Название: Изучаю Си (Массимы указателей)
Отправлено: Nikopol от 17 Июль, 2020, 13:27
Помогите пожалуйста.
Вот пример программы
вот эти места кода
отличаются только типом выводимых данных и * перед "р_..." Почему если тип int то нужно ставить *, а если char то нет? Если поставить * в char, т.е. написать "fprintf(stdout, "%s", *p_mass_string);" то компилятор выдаёт ошибку.
Вот здесь ещё пример. (http://www.c-cpp.ru/books/massivy-ukazateley)
Название: Re: Изучаю Си (Массимы указателей)
Отправлено: Slabovik от 21 Июль, 2020, 09:15
является массивом указателей, а не данных. "Данные" - это p_mass_string[SIZE_NUMBER], а *p_mass_string[SIZE_NUMBER] - это указатели.
Поэтому попытка вывести fprintf(stdout, "%s", *p_mass_string); закономерно приводит к ошибке типов.
Подробнее можно почитать, например здесь: https://metanit.com/cpp/tutorial/4.1.php но рекомендую начинать с малого, т.к. играясь с указателями на указатели, можно такого наворотить...
p.s. кстати, вот ещё чуток пояснений: https://ravesli.com/urok-82-ukazateli-i-massivy/
Название: Re: Изучаю Си (Массимы указателей)
Отправлено: Slabovik от 05 Авг., 2020, 16:24
Смотрю-смотрю и не пойму, либо я фигню здесь сморозил, либо что-то не так. Попробую своими словами, вне справочника.
Операция '*' - разыменование (название видится неудачным, но уж раз так прижилось, им и пользуемся). Разыменование имеет смысл тогда, когда есть некий адрес, по которому располагается некая переменная, а функции необходимо "скормить" саму переменную (данные). Собственно, это логика ЯВУ, когда вы прямо пишете формулы типа Z=X*Y
Здесь получается, что p_mass_string - это массив адресов (шесть позиций), показывающих на начала соответствующих строк. А *p_mass_string - это сами строки. Выходит, что выше как раз определяются строки, т.е. происходит их заполнение.
Цитата's' - Вывод строки, на которую ссылается указатель в аргументе функции printf (fprint). Строка выводится, пока не будет встречен признак конца строки (/0). По умолчанию строка должна обозначаться как char*.
Таким образом, звёздочка здесь не нужна - аргументом fprint и должен быть указатель.
Дальше немного чёрт ногу сломит (откуда вы берёте такие примеры?)
int num[SIZE_NUMBER] = {1, 2, 3, 4, 5, 6}; - тут вроде ясно. Если мы пишем num - фактически пишем само значение.
int *p1 = &num
;
- вот тут уже интересно. &num - указатель на num
Получается, в разыменованное (!) p прописываем в качестве значения указатель на num А само p1 - это указатель на место, где записан указатель на num
int *p_mass_num[SIZE_NUMBER] = {p1, p2, p3, p4, p5, p6}; - здесь получается массив *p_mass_num из указателей на указатели.
Посему получается, что в обоих случаях функции fprint скармливаются указатели на данные. Ну, а тип данных предваряется директивами (или как их там называют) форматирования.
Где я ошибся? Дело в том, что я сам перестал понимать, зачем fprint указатели, а не сами данные (со строкой-то понятно - там сама структура строк такая, хотя...)
ps: в любом случае, эти зубодробительные "преобразователи преобразователей" использовать в качестве учебных примеров настоятельно не советую. Потому что из-за того, "кто на ком стоял" сути не видно.
Название: Re: Изучаю Си (Массимы указателей)
Отправлено: Nikopol от 06 Авг., 2020, 17:40
Здорово, понятно и доходчиво, а то я уже весь мозг сломал. И почему то об этом нигде не написано. ;D