495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
|
||||||
1 | ||||||
Инкрементация указателя по членам класса22.12.2016, 20:25. Показов 601. Ответов 19
Метки нет Все метки)
(
Вот такая задачка у меня попалась на тестировании: "Корректен ли данный код? Если да, то что будет выведено на экран? Аргументируйте свой ответ. "
Но, вот уже дома проверил - выводит всегда 'y'. Это такое поведение по стандарту? Или тут что другое.
2
|
|
22.12.2016, 20:25 | |
Ответы с готовыми решениями:
19
не работает инкрементация указателя Создание указателя на экземпляр класса, описанного после объявления указателя Доступ к членам класса класса Доступ к членам класса |
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
|
||||||
23.12.2016, 00:31 [ТС] | 3 | |||||
Из всего этого делаем вывод что если одинаковые типы в классе идут один за другим, то по ним можно спокойно пробегаться указателем.
Добавлено через 4 минуты Даже в private получается залесть:
0
|
17411 / 9247 / 2260
Регистрация: 30.01.2014
Сообщений: 16,184
|
|
23.12.2016, 01:29 | 4 |
Для разных секций нет гарантии порядка. Так что этот код потенциально может породить выход за пределы объекта.
1
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|
23.12.2016, 01:33 | 5 |
DrOffset, а откуда такое утверждение? после компиляции нету секций и разделения на права доступа. Инициализация полей будет сверху вниз с объявления класса в любом случаи
0
|
17411 / 9247 / 2260
Регистрация: 30.01.2014
Сообщений: 16,184
|
|
23.12.2016, 01:38 | 6 |
При чем тут "после компиляции нет секций"?
Еще раз: нет гарантии порядка для переменных в разных секциях. Это значит, что в результате (в зависимости от реализации компилятора) может получиться как объект с лэяутом Код
<a> <b> Код
<b> <a> а , а затем инкрементируя его, мы вылетаем за границы объекта.
1
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|
23.12.2016, 01:42 | 7 |
DrOffset, так я и интересуюсь откуда у вас эта информация? Почему компиляторы могут изменить порядок класс-членом не "сверху-вниз" ?
0
|
17411 / 9247 / 2260
Регистрация: 30.01.2014
Сообщений: 16,184
|
|
23.12.2016, 01:50 | 8 |
rikimaru2013,
![]() Ты не интересуешься, а споришь, причем безосновательно. Порядок инициализации полей к рассматриваемому вопросу отношения не имеет. Добавлено через 4 минуты В новых черновиках эта цитата в 13м пункте, а не в 12. На всякий случай говорю.
7
|
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
|
|
23.12.2016, 01:51 | 9 |
DrOffset, А зачем такое поведение в стандарт ввели, это дает какую-то возможность компиляторам?
0
|
rikimaru2013
|
23.12.2016, 01:54
#10
|
Не по теме: Nosey, я тоже самое спрашивал - но меня оклеветали, что я спорю) :cry:
0
|
17411 / 9247 / 2260
Регистрация: 30.01.2014
Сообщений: 16,184
|
|
23.12.2016, 02:06 | 11 |
Насколько я знаю, в стандарте оно всегда было.
Про "зачем ввели" - свечку не держал (это значит, что далее идет мое личное мнение, которое может не соответствовать истине), но, возможно, это сделано чтобы дать возможность оптимизировать размер классов. В пределах одной секции порядок будет неизменен, но разные секции теоретически можно переставить местами в памяти, чтобы получить более компактный размер. Но, честно говоря, я не назову сейчас ни одного компилятора, который бы это делал на практике.
2
|
![]() 8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
|
|
23.12.2016, 12:05 | 12 |
0
|
Вездепух
![]() ![]() 10907 / 5904 / 1613
Регистрация: 18.10.2014
Сообщений: 14,832
|
|
23.12.2016, 12:16 | 13 |
Совершенно правильный ответ. Поведение такого кода будет не определено.
Так в вы чего ожидали? Что на мониторе загорятся большие красные буквы "поведение не определено"? Неопределенное поведение можно проявлять себя в том числе и как "работающий" код. Понятно, что на практике поля класса могу быть расположены в памяти компактно и вести себя фактически как элементы одного массива. Но это не меняет того факта, что язык формально не поддерживает такой адресной арифметики и поведение не определено. "Можно" в смысле "у меня все работало и у Васи Косого из второго подъезда, говорят, тоже работало". С точки зрения языка ничего подобного делать не разрешается.
1
|
![]() 8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
|
|
23.12.2016, 12:20 | 14 |
с фигали? оба чара в рамках одной секции будут идти друг за другом вплотную.
возможное выравнивание будет по границе однородных членов. язык никому ничего не запрещает.
0
|
Форумчанин
![]() ![]() 8194 / 5044 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
|
|
23.12.2016, 12:30 | 15 |
Надо было сразу на подобный глупый вопрос спросить:
А в скольких местах подобная конструкция используется в вашем production коде? Ответ "много где" - нахрена мне нужно поддерживать ваш быдлокод? Ответ "нигде" - нахрена мне нужно это тогда знать наизусть?
2
|
Вездепух
![]() ![]() 10907 / 5904 / 1613
Регистрация: 18.10.2014
Сообщений: 14,832
|
|
23.12.2016, 12:53 | 16 |
В С++ "друг за другом вплотную" идут только элементы одного массива. Все остальные "будут идти друг за другом вплотную" - не более чем особенности/совпадения/случайности конкретной реализации, к языку С++ никакого отношения не имеющие.
В язык С++ адресная арифметика определена только среди элементов одного массива. Никакой другой адресной арифметики в С++ нет. Язык С++ не дает никаких гарантий на тему того, где и как будут располагаться padding bytes в классе. Выравнивание в данном случае (и в любом другом случае) возможно где угодно и в неограниченных количествах. Речь идет о легальности конструкции и определенности поведения.
0
|
![]() 8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
|
|
23.12.2016, 13:21 | 17 |
такое поведение вполне объясняется банальным здравым смыслом.
не знаю ни один компилятор, который втыкал бы дырки между однородными членами. тем паче, что стандарт позволяет доступ к чару по неровному адресу. вставлять между ними дырки - это какой то бред.
0
|
Вездепух
![]() ![]() 10907 / 5904 / 1613
Регистрация: 18.10.2014
Сообщений: 14,832
|
|
23.12.2016, 13:32 | 18 |
Дело тут не в том, чтобы вставлять или не вставлять между ними дырки, а в том, что такой фичи, как итерирование/адресная арифметика по независимым полям класса в языке С++ просто нет.
0
|
![]() 8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
|
|
23.12.2016, 13:37 | 19 |
зато есть доступ к памяти, и возможность заинкрементить обычный указатель на данные.
стандарт не объявляет подобную ситуацию UB. насколько мне известно, он просто её не описывает. но по косвенным признакам, которые стандарт описывает, можно допустить, что подобный хак - не есть ill formed, а значит не есть UB
0
|
2761 / 1915 / 569
Регистрация: 05.06.2014
Сообщений: 5,571
|
|
23.12.2016, 14:42 | 20 |
Дык это любимый сишниками каламбур типизации. Вероятно, достался в нагрузку к библиотекам на "самом лучшем" языке.
0
|
23.12.2016, 14:42 | |
Помогаю со студенческими работами здесь
20
Доступ к членам класса Доступ к приватным членам класса
Доступ к private членам класса Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |