| 02.10.2014, 12:49 | |
|
Ответы с готовыми решениями:
72
безопасность и распространенные ошибки Распространенные ошибки SEO и ASP.NET 2.0 |
|
Вездепух
13203 / 6838 / 1822
Регистрация: 18.10.2014
Сообщений: 17,298
|
||
| 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
|
||
|
Модератор
13781 / 10974 / 6491
Регистрация: 18.12.2011
Сообщений: 29,259
|
|
| 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,977
|
|
| 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 | |
|
Помогаю со студенческими работами здесь
40
Самые распространенные строки Самые распространённые фамилии Вывести самые распространенные женские и мужские имена
Вирус блокирует выход на сайт вк и другие распространенные сайты Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2.
Задача: показать затраченные материалы за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом.
В качестве. . .
|
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2.
Задача: отобразить спецтехнику, которая на данный момент находится в ремонте.
Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
|
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
|
Запрет удаления строк ТЧ документа при определённом условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
|
|
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут
Суть:
- Группа наркоманов из 10 человек.
- Только один инфицирован ВИЧ.
- Колются одной иглой.
- Колются раз в день.
- Колются последовательно через. . .
|
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
|
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
|
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . .
а удачный момент так и не приходит.
|