| 02.10.2014, 12:49 | |
|
Ответы с готовыми решениями:
72
безопасность и распространенные ошибки Распространенные ошибки SEO и ASP.NET 2.0 |
|
Вездепух
13214 / 6847 / 1825
Регистрация: 18.10.2014
Сообщений: 17,338
|
||
| 28.10.2014, 19:55 | ||
|
12. scanf() - ввод текстовых строк
Такой вопрос обычно возникает у людей, которые считают, что массив физически представлен неким указателем на некий блок памяти. Соответственно ожидается , что '&mas' даст нам указатель на этот указатель и не будет работать в 'scanf'. Поэтому работоспособность такого 'scanf' зачастую вызывает удивление. На самом деле массивы в языке С не являются и никогда не являлись указателями. Это очень популярная легенда, которая никак не хочет умирать, несмотря на то, что материалов, объясняющих семантику С массивов написано очень много на всех языках. Массив - это просто непрерывный блок памяти, содержащий элементы массива. Т.е. например 'int a[20]' - это блок памяти из 20 объектов типа 'int'. И все. Имя 'a', как объект - это объект типа 'int [20]', который соответствует именно и только этому блок памяти. Никакого указателя там нигде нет. Иллюзия того, что массив "является указателем" возникает из-за того, что когда вы используете имя массива в выражениях, то почти всегда к массиву применяется неявное преобразование типа, которое автоматически "на лету" преобразует объект типа "массив" к временному значению "указатель на элемент". Этот указатель является rvalue и нигде не хранится в памяти. Он существует только концептуально - как результат вышеупомянутого неявного преобразования. Это чисто воображаемый указатель. По-английски явление "превращения" массива в указатель известно под устойчивым названием "array type decay". В стандарте языка С++ (где ситуация с массивами точно такая же) это неявное преобразование официально называется "array-to-pointer conversion". Но это неявное преобразование применяется не всегда. В языке С существует три контекста-исключения, в которых это неявное преобразование не делается: 1) Оператор 'sizeof'. Как известно 'sizeof(array)' возвращает размер всего массива, а не размер указателя на элемент. 2) Унарный оператор '&'. Возвращает указатель типа "указатель-на-весь-массив", а не "указатель-на-указатель" 3) Инициализация массива строковым литералом - 'char a[] = "Hello";'. Литерал '"Hello"' является массивом , но не деградирует до указателя в данном контексте. Таким образом, применение оператора '&' к объект типа "массив" дает вам указатель "на весь массив" (с точки зрения типа указателя). Т.е. для 'int a[20]' выражение '&a' имеет тип 'int (*)[20]'. В памяти адрес "всего массива" - это адрес того самого непрерывного блока, о котором я говорил выше. Т.е. численно этот адрес совпадает с адресом нулевого элемента массива. Именно поэтому выражения '&a', '&a[0]' и просто 'a' численно дают один и тот же адрес. Именно поэтому, к примеру, в функцию 'memcpy' для двух массивов (т.е. именно объектов типа "массив", а не "указатель") можно вызывать и как 'memcpy(dst, src, sizeof src)', и как 'memcpy(&dst, &src, sizeof src) и как 'memcpy(&dst[0], &src[0], sizeof src). Результат будет один и тот же во всех случаях. Именно поэтому правильно работает 'scanf' при использовании 'mass' или '&mass', ибо оба выражения дают одно и то же физическое численное значение. (Второй вариант формально не верен, т.к. формат '%s' требует указателя именно типа 'char *', а не 'char (*)[N]', но на практике это не важно.) Кстати, Денис Ритчи в своей статье об истории происхождения С (http://cm.bell-labs.com/who/dmr/chist.html) пишет, что изначально он собирался реализовать массивы в С точно так же, как они были реализованы в языках B и BCPL. В B и BCPL массивы были реализованы именно как самостоятельные указатели, указывающие на отдельные посторонние блоки памяти. Но Ритчи также хотел ввести в язык такой новый тип, как структуры. И тут сразу возникла проблема: если массив будет реализован через указатель, то структуру, содержащую в себе массивы, невозможно будет тривиально копировать. Т.е. обычный 'memcpy' будет тупо копировать указатели из одной структуры в другую. А это, разумеется, неприемлемо. По этой причине он отказался от идеи реализовывать массивы через физические указатели. Массивы в С стали просто блоками памяти. Никаких указателей. Но для сохранения похожей на B и BCPL семантики в язык С было введено неявное преобразование из типа "массив" в тип "указатель". Большинство операций с массивами работает именно через это преобразование, т.е. через временный указатель. Но физически этого указателя не существует.
14
|
||
|
Модератор
13789 / 10981 / 6492
Регистрация: 18.12.2011
Сообщений: 29,284
|
|
| 06.01.2015, 13:26 [ТС] | |
|
Приведение типа в стиле С++
Язык С++ позволяет использовать приведение типа как в виде (int)x, так и int(x) Для С допустим только первый (int)x вариант!
1
|
|
|
|
|||||||||||||
| 03.03.2015, 10:33 | |||||||||||||
|
Вставлю все-же свои 5 копеек.
TheCalligrapher, вы в своем изложении не учли одно важное обстоятельство, которое подвело вас, а может и читателей, к опасному выводу. А именно: Почему же оба кейса отрабатывают верно? Тут, в моем понимании, дело в следующем. Оба примера внутри работают с объектами в памяти через char* (в scanf посредством кастинга va_arg, и в memcpy работы с char буферами). И работает сие счастье только потому, что char* именно для этих целей (работы с памятью) был сделан универсальным type-aliasом. В контексте сказанного, ошибочно полагать, что
0
|
|||||||||||||
|
|
||
| 03.03.2015, 14:04 | ||
|
0
|
||
|
|
|||
| 03.03.2015, 14:44 | |||
|
Не по теме: Да ради бога. Добавлено через 17 минут Не по теме: @Модераторам просьба: обрежьте пост Распространенные ошибки после предложения
0
|
|||
| 03.03.2015, 15:17 | |
|
Не по теме: До фразы "на этом можно поставить точку" кроме мысли о формальном UB (да и то я на 100% не уверен, что приведение указателя на массив к указателю на элемент массива приводит к UB) всё остальное тоже можно удалять. Имеется в виду про "не учли одно важное обстоятельство, которое подвело вас, а может и читателей, к опасному выводу", потому что в том описании всё разжёвано предельно ясно, а потому как-то тут не понятно, какие опасные выводы кто-то мог бы вывести
0
|
|
|
Модератор
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,981
|
|
| 03.03.2015, 15:23 | |
|
0
|
|
|
|
||||||||||||||||||||||||
| 04.03.2015, 10:25 | ||||||||||||||||||||||||
|
Поскольку я упертый как 100 баранов, то все-же попытаюсь опровергнуть мысль, а именно выделенные тезисы:
Первое. C89 п.7.19.6.1/8 для формата %s:
Теперь к с случаю с memcpy. Рассмотрим пример:
Надеюсь теперь мысль более доступно изложена.
2
|
||||||||||||||||||||||||
|
|
||||
| 04.03.2015, 12:30 | ||||
|
0
|
||||
|
|
||
| 04.03.2015, 14:42 | ||
|
Добавлено через 21 минуту
0
|
||
|
|
||
| 04.03.2015, 14:42 | ||
|
В твоей цитате сказано "the argument shall be a pointer to the initial element of an array of character type". Под такую формулировку попадают и char*, и volatile char*, и char(*)[], а так же всякие int*, которые указывают на первый элемент массива char'ов
0
|
||
|
|
||||||||
| 04.03.2015, 16:30 | ||||||||
|
В сорцах glibc (2.21 -- /libc/stdio-common/printf-parse.h) нашел список форматов для парсера этой группы функций:
0
|
||||||||
|
|
||
| 04.03.2015, 16:40 | ||
|
0
|
||
|
|
|
| 04.03.2015, 16:55 | |
|
Evg, не совсем понял ход вашей мысли. Пусть адреса совпадают. Что это нам дает в контексте обсуждения?
0
|
|
|
|
||
| 04.03.2015, 17:54 | ||
|
0
|
||
|
|
|
| 04.03.2015, 19:04 | |
|
Evg, теперь я вашу мысль понял. Если сможете найти такой, то я, да и огромная часть SO-коммьюнити будет в неоплатном долгу.
0
|
|
|
|
||
| 04.03.2015, 21:35 | ||
Мне лениво, потому что не совсем понятно, что конкретно надо искать. Всё-таки я не читаю стандарт перед сном и кроме как поиском там фиг что могу найти
0
|
||
|
|
||
| 05.03.2015, 08:23 | ||
|
Evg, поищу конечно, но 50/50, т.к. если не найду, это не будет значить, что его там нет. Это будет лишь значить, что я не нашел и только. В таком контексте я вроде уже сразу на проигравшей стороне
0
|
||
|
|
|||
| 05.03.2015, 12:03 | |||
|
1
|
|||
|
|
|
| 05.03.2015, 12:32 | |
|
0
|
|
| 05.03.2015, 12:32 | |
|
Самые распространенные строки Самые распространённые фамилии Вывести самые распространенные женские и мужские имена
Вирус блокирует выход на сайт вк и другие распространенные сайты Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
| Опции темы | |
|
|
Новые блоги и статьи
|
|||
|
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F
Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU.
Опрашиваются регистры. . .
|
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка:
Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
|
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо
Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
|
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман.
Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
|
|
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
|
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
|
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ
Основная суть и тезисы по измерениям:
0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема.
Объект не может перемещаться в 0D.
1D (Первое измерение):. . .
|
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek
ВВЕДЕНИЕ
Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
|