Ошибка №7. Операции над указателями. Арифметика.
Запись от steelcraft размещена 27.06.2024 в 01:46
Показов 5327
Комментарии 75
|
Указатели, пожалуй, самая интересная тема в языке C. Собственно, больше ничего интересного в нем и нет, все остальное очевидно и просто. Именно указатели придают этому языку его силу и одновременно опасность. Неудивительно, что большинство ошибок на собеседованиях вызывает именно эта тема. Итак, очередной вопрос: перечислите операции над указателями. Как правило, операции поименования (&) и разыменования (*) проблем не вызывают. Далее черед доходит до адресной арифметики. Тут появляются первые симптомы: есть некоторое количество кандидатов, которые вообще не знают, что это такое. Как правило, это люди, которые специализируются в области электроники, а на C пишут лишь небольшие фрагменты, чтобы проверить работоспособность макета. В продукцию этот код не идет. В этом случае на этом дискуссию сворачиваем и переходим ко второй части собеседования - по электронике (за редким исключением эмбеддеры собеседуются по двум дисциплинам сразу). Бывает и такой ответ: поскольку указатель - это адрес, а адрес - это целое число, то над указателями можно делать любые арифметические операции. Определенная логика тут, конечно присутствует (о том, является ли указатель в действительности адресом, поговорим отдельно), но возникает вопрос: какова семантика результата? Что дает перемножение, деление или сложение адресов (про вычитание пока молчок, это отдельная тема)? Типичная реакция - пожимание плечами. Те, кто изучал язык более тщательно, называют еще две допустимые операции: прибавление/вычитание целочисленной величины к указателю. Тут кроются еще две тонкости (правда, все же относительно толстые). 1. Каков результат прибавления целой величины k к указателю p? Плохой ответ: указатель смещается на k байтов относительно исходного положения. Хороший ответ: величина умножается на размер типа, на который указывает p, и полученное число используется как смещение указателя. Для вычитания верно то же самое. Вопрос довольно легкий, и с ним успешно справляется довольно большое число кандидатов. 2. При каком условии полученное новое значение указателя валидно? Тут обычно дело гораздо хуже, лишь небольшое количество кандидатов дает правильный ответ. Это уже показатель продвинутого уровня и дает возможность претендовать на миддла. Правильный ответ: если указатель указывал на элемент некоторого массива, и после смещения продолжает указывать на элемент этого же массива или на ячейку памяти непосредственно за концом массива, такая операция валидна. В противном случае возникает неопределенное поведение. В стандарте ISO/IEC 9899:2018 эта ситуация описана в разделе 6.5.6 "Additive operators", п. 8 (стр. 67). Итак, приходим к соглашению: к указателю можно прибавить (либо вычесть) целочисленное значение, и при определенных условиях мы получим новое значение указателя, смещенное на несколько элементов относительно исходного. Умножение, деление и сложение указателей не имеет никакого смысла. Вычитание указателей я пока обхожу, это тема отдельного вопроса. |
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 75
Комментарии
-
Запись от sporta1982 размещена 28.06.2024 в 11:51
-
А линуксовые хакеры когда-то обходились без const char *:
https://source.puri.sm/Librem5... arch.c#L42C 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
void *bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp)(const void *key, const void *elt)) { size_t start = 0, end = num; int result; while (start < end) { size_t mid = start + (end - start) / 2; result = cmp(key, base + mid * size); // арифметика const void * if (result < 0) end = mid; else if (result > 0) start = mid + 1; else return (void *)base + mid * size; // ещё одна } return NULL; }
Запись от politoto размещена 28.06.2024 в 12:36
-
Запись от CoderHuligan размещена 28.06.2024 в 14:34
-
А компилятору будет известен полный тип объекта, на который может ссылаться указатель, в том числе размер объекта.
Что позволит компилятору правильно обрабатывать адресную арифметику, а не выдумыватьsizeof mainиsizeof void.
Результат арифметических операции, если он будет указателем, можно явно или неявно преобразовать в void*.Запись от politoto размещена 28.06.2024 в 15:35
-
Так смысл void* в том, что это есть указатель на любой тип объекта. Указатель может обрабатывать объекты разных типов (после приведения). Единственно к чему его не надо приводить, это к типу байта. В расширении Си. На лицо экономия в операциях. Конфликт теоретиков и практиков. Язык Си создавали практики.Потом его испортили теоретики (почти испортили..)Запись от CoderHuligan размещена 28.06.2024 в 15:41
-
Практики-изобретатели не изобретали voidовЗапись от politoto размещена 28.06.2024 в 16:04
-
Запись от Croessmah размещена 28.06.2024 в 17:30
-
Запись от sporta1982 размещена 29.06.2024 в 12:10
-
Пока приплюснутые не захватили власть в комитете по стандартизации Си, было все нормально и не было необходимости в void, как то обходились char*. И malloc возвращал именно char*.
То что sizeof возвращает не тип обобщенного указателя, а размер машинного адреса, это к тем кто перепил. А расширение gcc просто исправили эту ошибку, и то это костыль.Запись от CoderHuligan размещена 29.06.2024 в 17:40
-
А знаете почему? Потому что void это "ничто", то есть нечто не имеющее типа. Поэтому возвращать тип char было не кошерно.)) Так подумали они.. Но что-то же надо было возвратить через sizeof? В си нет типа "указатель". Есть тип "указатель на какой-то реальный тип". Но эти молодцы посчитали: да хай с ним, пусть будет просто указатель, на том и порешили.))В компюьтере же нет ни единой сущности, которая была бы void.
На какой же тип должен указывать void*? Естественно на производный тип - однобайтовый char, из которого составлены остальные типы. То есть никакого смысла в void* просто не было.Запись от CoderHuligan размещена 29.06.2024 в 18:14
-
Запись от Croessmah размещена 29.06.2024 в 20:57
-
Запись от sporta1982 размещена 29.06.2024 в 22:38
-
Запись от CoderHuligan размещена 30.06.2024 в 07:28
-
Ну тут явная ошибка собеседователя во всех этих ошибках. Все эти знания должен проверять препоод принимающий лабораторные работы на 1-ом курсе (т.е. без этого даже к экзаменам не допуустят не то что диплом не выдадут). Не надо считать разрабов идиотами еле-еле умеющими как то шкарябать на языке. Задача собеседования - проверить уровень инженерного мышления разработчика - именно это показатель квалификации, а знание языка - это как бы порог вхождерния не в работу, а в изучение специальности. Т.е. с таким подходом к собеседовниям вы будете набирать исключительно неучей. Потому что уважающий себя инженер прекратит собеседоваание после первого же вопроса. Прчина надеюсь понятна - если у конторы такой контингент которому нуужно устраивать входной контроль по таким вопроосам, то это контора потенциальный банкрот в ближайшее времяя и искать интересные задачи и нормальные зароботки в этой конторе нечего, придется перелопачиваь тонны хаотичесеки нацарапанного оным контингентом аки курица лапой легаси и все равно переделать все с нуля, против чего контора будет упираться во всю ибо типа необразованный контингент не поймет.Запись от Fulcrum_013 размещена 30.06.2024 в 15:08
-
Предложите идеи, как за пару часов отличить реально хорошего инженера от кое-какера. Тестовое задание, естественно, не годится: его долго делать и долго проверять. К тому же заставлять кандидата делать прототип за свой счет не совсем правильно, не у каждого дома есть полноценная электронная лаборатория (хотя у фанатиков своего дела, конечно, есть).Запись от steelcraft размещена 30.06.2024 в 15:34
-
Поговорите про архитектуру. Про отличия реалтайма от нереалтайма и т.п. Про подход к компонентному построению систем и т.д. Умение строить абстракции и описывать процессы системами уравнений. Сразу видно имеет ли человек мыслить как инженер или нет. Если умеет то язык знает (и скорее всего не один) и умения практического использования тоже имеет (без практического пременения все эти архитектурные дела даже близко не осилить). Т.е. говорите с ним как с квалифицированым спецом а не проверяйте умеет ли он ручкой пользоваться. Исходите из того что действительно годный спец сам в состоянии выбрать язык реализации для задачи, причем абсолютно аргументированно, и если с ним на практике не знаком то изучить его по мануалу за пару дней (со знанием С и С++ которые в универах первый язык на сегодняшний день это плевая задача обычно), а то и спроектировать более подходящий если его нет (именно такова история появления и С и С++). Тогда понятно кого к следующим стадиям допускать кого нет. Ну с кем то придется корректировать позиции уже после найма. Отличить годного спеца от ворд-топ класса в процессе только собеседований действительно нереальню.
Ну и опять же - потенциально годный кандидат имеет диплом по специальности. Для реально специалистов вопрос обычно стоит в годности конторы для спеца (не получится ли стрельбы из пушки по воробьям и как результат конфликта интересов) а не в годности спеца для этой работы.
А насчет умения работать с кодом - это проверяют обычно уже не на первом собеседовании а на последнем. Т.е. уже когда познакомили с командой и обсудили все эти подходы к архитектуре еще и с командой. И выглядит это примерно так - дают отрефакторить код и смотрят как это делаешь всей командой. При этом стараются дать не на том языке который указан основным, а на одном из вторичных указанных в CV. Расчитано минут на 15. Но если спец реально годный то реально минуты через 2-3 уже становится понятно что проверять собственно говоря больше нечего. Т.е. проверяется УМЕНИЕ решать проблемы с мало знакомой технологией/языком. Естествеенно чо если это умение есть то за основной исполььзуемый язык можно даже в проерки не лезть - т.е. есть умение и избегать багов и их отлаживать и тестировать и т.д.Запись от Fulcrum_013 размещена 30.06.2024 в 15:50
-
Дело в том, что нужны работники разного уровня, в том числе и лаборанты. Задача собеседования - максимально точно определить уровень конкретного кандидата. Если кто-то не отвечает на какой-то вопрос, это вовсе не значит, что он не принят, просто ему будет предложена позиция пониже. Как Вы понимаете, говорить об архитектуре с лаборантом - затея обреченная для обеих сторон.
В реале собеседование не проходит по всему набору вопросов, которые я пытаюсь вспомнить. Тут больше похоже на двоичный поиск: задаю вопрос примерно средней сложности; если ответ хороший - переходим к верхней половине, если нет - к нижней. Три-четыре итерации - и картина максимально проясняется, можно переходить к вопросам по схемотехнике. Это не изнурительный нудный экзамен по азам.
На самом деле такое было всего раз за несколько сотен собеседований. Причем кандидат производил странное впечатление: неопрятно одет, непричесан, как-то взвинчен (дело было в ковидные времена, собеседовали удаленно). На просьбу ответить на несколько вопросов устроил истерику. Большинство с интересом включаются в обсуждение. В конце часто благодарят за интересное собеседование.
Сообщение от Fulcrum_013
P.S. Мне реально очень интересны идеи других людей, поскольку сам я никогда в жизни не проходил собеседования и не знаю, как проводят собеседования другие.Запись от steelcraft размещена 30.06.2024 в 16:23
-
В принципе идея мне нравится, но... Вот взять мой случай: у меня во вторичных языках значатся C# и Ruby. Но для них тестирование устроено совсем не так, как на C. Настолько не так, что я долго не мог решиться войти в эмбеддинг (привык к TDD/ATDD, а в С с этим долгое время было из рук вон плохо). Поэтому я произвел бы тогда обманчивое благоприятное впечатление, вообще не умея тестировать код C и даже не представляя, как это делается.
Сообщение от Fulcrum_013
Запись от steelcraft размещена 30.06.2024 в 16:55
-
Запись от Fulcrum_013 размещена 30.06.2024 в 17:11
-
Да точно так же как и все остальное только без поддержки IDE. Т.е. тестируемыые либы подключаются к проекту содержащему тесты который вызывает функции и сравнивает выхлоп с набором данных только результаты в консоль.
Сообщение от steelcraft
Да в принципе это даже и не смотрят. Смотрят способен ли самостоятельно решить задачу рефакторинга - т.е. не просто изобрести кота с нуля а разобраться в чужом коде и причисать его в соответстви со спецификацией. А дальше все просто - нужны тесты будут тесты. Тесты это в принципе точно такая же программа.Запись от Fulcrum_013 размещена 30.06.2024 в 17:16


просим
