| 02.10.2014, 12:49 | |
|
Ответы с готовыми решениями:
72
безопасность и распространенные ошибки Распространенные ошибки SEO и ASP.NET 2.0 |
|
Вездепух
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,312
|
||
| 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,281
|
|
| 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,980
|
|
| 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 | |
|
Самые распространенные строки Самые распространённые фамилии Вывести самые распространенные женские и мужские имена
Вирус блокирует выход на сайт вк и другие распространенные сайты Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С.
Задача:
Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
|
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
|
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
|
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701
Купил два термопринтера QR701.
На сэлф-тесте написано:
Language: PC936 (GB18030).
Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
|
|
Создание формы заимствованного документа
Maks 03.08.2026
Задача:
Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также
табличная часть со следующими реквизитами:
- Расчетный счет покупателя. . .
|
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача:
В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
|
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов.
Логика кажется понятной:
1. Находим ключевые слова.
2. Добавляем их на. . .
|
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302
Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
|