495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
1

Инкрементация указателя по членам класса

22.12.2016, 20:25. Показов 601. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот такая задачка у меня попалась на тестировании: "Корректен ли данный код? Если да, то что будет выведено на экран? Аргументируйте свой ответ. "
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
struct C
{
    char a, b;
};
 
int main()
{
    C c;
    c.a = 'x';
    c.b = 'y';
    char* pc = &c.a;
    pc++;
    std::cout << *pc;
}
Я ответил, что результат не определен из за выравнивания в классе и инкрементация указателя может указывать на не корректную память. Следовательно, может вывести как 'y' так и мусор.
Но, вот уже дома проверил - выводит всегда 'y'. Это такое поведение по стандарту? Или тут что другое.
2
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.12.2016, 20:25
Ответы с готовыми решениями:

не работает инкрементация указателя
кинул мне сегодня знакомый програмку...нужно было переделать ее с использованием указателя суть...

Создание указателя на экземпляр класса, описанного после объявления указателя
Здравствуйте! Проблема в том, что нужно сделать так: class A{ public: B* b = nullptr; }; ...

Доступ к членам класса класса
Всем привет. Вобщем есть базовый класс, и два производных. Пользователь вводит координаты нужно...

Доступ к членам класса
Объект класса не может получить доступ к своим переменным?

19
114 / 112 / 62
Регистрация: 15.03.2013
Сообщений: 561
Записей в блоге: 5
22.12.2016, 21:07 2
Нашел вот такую инфу в интернете
Выравниваются в памяти поля по границе кратной своему же размеру. То есть 1-байтовые поля не выравниваются, 2-байтовые — выравниваются на чётные позиции, 4-байтовые — на позиции кратные четырём и т.д.
1
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
23.12.2016, 00:31  [ТС] 3
Из всего этого делаем вывод что если одинаковые типы в классе идут один за другим, то по ним можно спокойно пробегаться указателем.

Добавлено через 4 минуты
Даже в private получается залесть:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct C
{
    short a;
private:
    short b = 20;
};
 
int main()
{
    C c;
    c.a = 2;
    short* p = &c.a;
    p++;
    std::cout << "p = " << *p << "\n"; // 20
}
0
17411 / 9247 / 2260
Регистрация: 30.01.2014
Сообщений: 16,184
23.12.2016, 01:29 4
Цитата Сообщение от notAll Посмотреть сообщение
Даже в private получается залесть
Для разных секций нет гарантии порядка. Так что этот код потенциально может породить выход за пределы объекта.
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
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
а откуда такое утверждение? после компиляции нету секций и разделения на права доступа
При чем тут "после компиляции нет секций"?
Еще раз: нет гарантии порядка для переменных в разных секциях. Это значит, что в результате (в зависимости от реализации компилятора) может получиться как объект с лэяутом
Код
<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,
Цитата Сообщение от 9.2/12
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
Добавлено через 2 минуты
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
так я и интересуюсь откуда у вас эта информация?
Ты не интересуешься, а споришь, причем безосновательно.

Цитата Сообщение от 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
Цитата Сообщение от Nosey Посмотреть сообщение
А зачем такое поведение в стандарт ввели, это дает какую-то возможность компиляторам?
Насколько я знаю, в стандарте оно всегда было.
Про "зачем ввели" - свечку не держал (это значит, что далее идет мое личное мнение, которое может не соответствовать истине), но, возможно, это сделано чтобы дать возможность оптимизировать размер классов. В пределах одной секции порядок будет неизменен, но разные секции теоретически можно переставить местами в памяти, чтобы получить более компактный размер. Но, честно говоря, я не назову сейчас ни одного компилятора, который бы это делал на практике.
2
Эксперт С++
8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
23.12.2016, 12:05 12
Цитата Сообщение от ящюр Посмотреть сообщение
Нашел вот такую инфу в интернете
ложь.
0
Вездепух
Эксперт CЭксперт С++
10907 / 5904 / 1613
Регистрация: 18.10.2014
Сообщений: 14,832
23.12.2016, 12:16 13
Цитата Сообщение от notAll Посмотреть сообщение
Я ответил, что результат не определен из за выравнивания в классе и инкрементация указателя может указывать на не корректную память. Следовательно, может вывести как 'y' так и мусор.
Совершенно правильный ответ. Поведение такого кода будет не определено.

Цитата Сообщение от notAll Посмотреть сообщение
Но, вот уже дома проверил - выводит всегда 'y'. Это такое поведение по стандарту? Или тут что другое.
Так в вы чего ожидали? Что на мониторе загорятся большие красные буквы "поведение не определено"? Неопределенное поведение можно проявлять себя в том числе и как "работающий" код. Понятно, что на практике поля класса могу быть расположены в памяти компактно и вести себя фактически как элементы одного массива. Но это не меняет того факта, что язык формально не поддерживает такой адресной арифметики и поведение не определено.

Цитата Сообщение от notAll Посмотреть сообщение
Из всего этого делаем вывод что если одинаковые типы в классе идут один за другим, то по ним можно спокойно пробегаться указателем.
"Можно" в смысле "у меня все работало и у Васи Косого из второго подъезда, говорят, тоже работало".

С точки зрения языка ничего подобного делать не разрешается.
1
Эксперт С++
8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
23.12.2016, 12:20 14
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Совершенно правильный ответ. Поведение такого кода будет не определено.
с фигали? оба чара в рамках одной секции будут идти друг за другом вплотную.
возможное выравнивание будет по границе однородных членов.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
С точки зрения языка ничего подобного делать не разрешается.
язык никому ничего не запрещает.
0
Форумчанин
Эксперт CЭксперт С++
8194 / 5044 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
23.12.2016, 12:30 15
Цитата Сообщение от notAll Посмотреть сообщение
Вот такая задачка у меня попалась на тестировании:
Надо было сразу на подобный глупый вопрос спросить:
А в скольких местах подобная конструкция используется в вашем production коде?
Ответ "много где" - нахрена мне нужно поддерживать ваш быдлокод?
Ответ "нигде" - нахрена мне нужно это тогда знать наизусть?
2
Вездепух
Эксперт CЭксперт С++
10907 / 5904 / 1613
Регистрация: 18.10.2014
Сообщений: 14,832
23.12.2016, 12:53 16
Цитата Сообщение от hoggy Посмотреть сообщение
с фигали? оба чара в рамках одной секции будут идти друг за другом вплотную.
В С++ "друг за другом вплотную" идут только элементы одного массива. Все остальные "будут идти друг за другом вплотную" - не более чем особенности/совпадения/случайности конкретной реализации, к языку С++ никакого отношения не имеющие.

В язык С++ адресная арифметика определена только среди элементов одного массива. Никакой другой адресной арифметики в С++ нет.

Цитата Сообщение от hoggy Посмотреть сообщение
возможное выравнивание будет по границе однородных членов.
Язык С++ не дает никаких гарантий на тему того, где и как будут располагаться padding bytes в классе. Выравнивание в данном случае (и в любом другом случае) возможно где угодно и в неограниченных количествах.

Цитата Сообщение от hoggy Посмотреть сообщение
язык никому ничего не запрещает.
Речь идет о легальности конструкции и определенности поведения.
0
Эксперт С++
8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
23.12.2016, 13:21 17
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В С++ "друг за другом вплотную" идут только элементы одного массива. Все остальные "будут идти друг за другом вплотную" - не более чем особенности/совпадения/случайности конкретной реализации, к языку С++ никакого отношения не имеющие.
такое поведение вполне объясняется банальным здравым смыслом.
не знаю ни один компилятор, который втыкал бы дырки между однородными членами.
тем паче, что стандарт позволяет доступ к чару по неровному адресу.
вставлять между ними дырки - это какой то бред.
0
Вездепух
Эксперт CЭксперт С++
10907 / 5904 / 1613
Регистрация: 18.10.2014
Сообщений: 14,832
23.12.2016, 13:32 18
Цитата Сообщение от hoggy Посмотреть сообщение
тем паче, что стандарт позволяет доступ к чару по неровному адресу.
вставлять между ними дырки - это какой то бред.
Дело тут не в том, чтобы вставлять или не вставлять между ними дырки, а в том, что такой фичи, как итерирование/адресная арифметика по независимым полям класса в языке С++ просто нет.
0
Эксперт С++
8725 / 4305 / 958
Регистрация: 15.11.2014
Сообщений: 9,752
23.12.2016, 13:37 19
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Дело тут не в том, чтобы вставлять или не вставлять между ними дырки, а в том, что такой фичи, как итерирование/адресная арифметика по независимым полям класса в языке С++ просто нет.
зато есть доступ к памяти, и возможность заинкрементить обычный указатель на данные.
стандарт не объявляет подобную ситуацию UB.
насколько мне известно, он просто её не описывает.
но по косвенным признакам, которые стандарт описывает,
можно допустить, что подобный хак - не есть ill formed,
а значит не есть UB
0
2761 / 1915 / 569
Регистрация: 05.06.2014
Сообщений: 5,571
23.12.2016, 14:42 20
Цитата Сообщение от MrGluck Посмотреть сообщение
Ответ "много где" - нахрена мне нужно поддерживать ваш быдлокод?
Дык это любимый сишниками каламбур типизации. Вероятно, достался в нагрузку к библиотекам на "самом лучшем" языке.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.12.2016, 14:42
Помогаю со студенческими работами здесь

Доступ к членам класса
Есть два класса: #include &quot;stdafx.h&quot; #include &lt;iostream&gt; using namespace std; class CPerson...

Доступ к приватным членам класса
Хочу я иметь доступ к приватному члену класса. Зачем это надо - за рамками данной темы и не...

Обращение к элементам, членам класса
Здравствуйте! Мне нужно выполнить задания из меню (в коде программы), но я не могу понять как...

Доступ к private членам класса
Почему при таком объявлении не работает оператор вывода, по идее он же объявлен как друг класса и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru