Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705

Sizeof: как правильно найти размер авторского типа?

18.10.2014, 13:32. Показов 2484. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
using namespace std;
 
class kl
{
};
 
 
///////////////////////////////////////
 
int main ()
{
 printf ("%d\n", sizeof(kl));
 getchar ();
}
Прочитал стандарт 5.3.3.1 и 5.3.3.2 и так и не понял, почему у меня под элементы типа kl выделяется 1 байт. В объекте этого типа должно храниться как минимум три указателя: (на конструктор, не деструктор и на конструктор копирования), это уже 12 байт. В общем, спасибо, кто откликнется.
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
18.10.2014, 13:32
Ответы с готовыми решениями:

Как вывести размер типа данных в байтах не используя функцию sizeof?
Всем привет, не подскажете как вывести размер типа данных в байтах не используя функцию sizeof?

Правильно ли определять размер объекта класса операцией sizeof?
будет ли правильно определить размер объекта класса операцией sizeof() ? чойто у меня неадекватные цыфры выдаёт, как мне кацца:dance:

Как правильно выбрать размер локального типа-массива
Преподаватель задал вопрос, ответить надо в строгой форме, а у меня с собой нет даже методички, помогите: Как правильно выбрать размер...

20
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
18.10.2014, 13:36
Цитата Сообщение от kravam Посмотреть сообщение
В объекте этого типа должно храниться как минимум три указателя: (на конструктор, не деструктор и на конструктор копирования)
Указатели на методы не хранятся в объекте класса, если пользователь явно того не написал.
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
18.10.2014, 13:37
Цитата Сообщение от kravam Посмотреть сообщение
В объекте этого типа должно храниться как минимум три указателя:
не должны
нет виртуальных функций
а размер один байт, потому что нет размера 0 байт
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
18.10.2014, 13:37
Цитата Сообщение от kravam Посмотреть сообщение
В объекте этого типа должно храниться как минимум три указателя: (на конструктор, не деструктор и на конструктор копирования), это уже 12 байт.
Указатели на обычные (не виртуальные) методы, включая конструкторы и деструкторы,
не хранятся в объектах, класса, это было бы слишком расточительно.
Потому что объектов много, а методы общие, проще хранить их в одном месте.

Не по теме:

сколько желающих набралось за 1 минуту :)

0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
18.10.2014, 13:42
Цитата Сообщение от Убежденный Посмотреть сообщение
Указатели на обычные (не виртуальные) методы
да там чаше всего и нет никаких указателей
метод типа MyClass::MyMetod()
превратится во что то типа
MyClass_MyMetod(MyClass* this)
обыкновенная функция просто добавляется один аргумент, указатель на объект
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
18.10.2014, 14:09
Цитата Сообщение от ValeryS Посмотреть сообщение
потому что нет размера 0 байт
гэ-цэ-цэшечка:
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
struct S
{
    int i[];
};
 
int main() {
    std::cout << sizeof(S) << std::endl;
}
http://coliru.stacked-crooked.... 38780d23f4

Добавлено через 2 минуты
Цитата Сообщение от Убежденный Посмотреть сообщение
Указатели на обычные (не виртуальные) методы, включая конструкторы и деструкторы, не хранятся в объектах,
<pedantic>
Так и на виртуальные методы не хранятся. Хранится указатель (единственный) на таблицу виртуальных методов, а не на сами методы.
</pedantic>
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
18.10.2014, 14:16
Цитата Сообщение от Tulosba Посмотреть сообщение
std::cout << sizeof(S) << std::endl;
и это правильно?
а где размер указателя?
и как поведет себя при таком
C++
1
2
3
S* a=new S;
S* b=new S;
S* c=new S;
неужто выделит все по одному адресу?
насколько помню размер один байт и сделан был, чтобы от этой бяки освободится
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
18.10.2014, 14:26
Цитата Сообщение от ValeryS Посмотреть сообщение
неужто выделит все по одному адресу?
Для чистоты эксперимента надо для массива выделять, а не для несвязанных переменных.
http://coliru.stacked-crooked.... f478e30340
И обрати внимание теперь на опцию -pedantic и соответствующий ворнинг.
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
18.10.2014, 14:31
Цитата Сообщение от Tulosba Посмотреть сообщение
гэ-цэ-цэшечка:
Так это вообще не стандартный C++ (и даже не C)...
0
 Аватар для p_r_a_g_m_a
112 / 64 / 23
Регистрация: 08.03.2012
Сообщений: 211
18.10.2014, 14:31
Цитата Сообщение от Tulosba Посмотреть сообщение
гэ-цэ-цэшечка:
Та да:
http://coliru.stacked-crooked.... 10519c20d4
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
18.10.2014, 14:32
Для C++ - это фича gcc, в C99/11 - это incomplete type, так что там вообще undeclared identifier для S.
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
18.10.2014, 14:38
а вот что сказал VS2008
1>c:\users\noutdns\documents\visual studio 2008\projects\test22\test22\test22.cpp(1 0) : warning C4200: нестандартное расширение: массив нулевого размера в структуре (объединении)
1> Невозможно создать конструктор копии или оператор присвоения копии, когда UDT содержит массив нулевого размера
1>c:\users\noutdns\documents\visual studio 2008\projects\test22\test22\test22.cpp(1 7) : error C2233: Target of operator new(): недопустимый массив объектов, содержащий массивы нулевого размера
немного изменил код

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
struct S
{
  //  int i[];
};
 
int main() {
    std::cout << sizeof(S) << std::endl;
    
    const int n = 10;
    S* s = new S[n];
    for( int i=0; i<n; ++i )
        std::cout << &s[i] << std::endl;
 
 
}
и все пошло как надо
1
004D4E50
004D4E51
004D4E52
004D4E53
004D4E54
004D4E55
004D4E56
004D4E57
004D4E58
004D4E59
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
18.10.2014, 15:53
Цитата Сообщение от Somebody Посмотреть сообщение
Так это вообще не стандартный C++ (и даже не C)...
Я в курсе. Это всё расширения. https://gcc.gnu.org/onlinedocs... Structures
Цитата Сообщение от p_r_a_g_m_a Посмотреть сообщение
Та да:
Ненулевым размером никого не удивишь
0
 Аватар для p_r_a_g_m_a
112 / 64 / 23
Регистрация: 08.03.2012
Сообщений: 211
18.10.2014, 15:55
Цитата Сообщение от Tulosba Посмотреть сообщение
Ненулевым размером никого не удивишь
Я к тому, что int i[] по идее должен быть тоже равен (как и int* i) 4-8
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
18.10.2014, 15:58
Цитата Сообщение от p_r_a_g_m_a Посмотреть сообщение
Я к тому, что int i[] по идее должен быть тоже равен (как и int* i) 4-8
Неа. Тут массив неизвестной длины используется лишь для удобства доступа к ячейкам памяти. Вчера как раз на этот счет отписывался.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
18.10.2014, 17:41
Цитата Сообщение от p_r_a_g_m_a Посмотреть сообщение
Я к тому, что int i[] по идее должен быть тоже равен (как и int* i) 4-8
Нет. Пустые массивы внутри структур используют для динамически выделяемых структур, чтобы регулировать размер выделяемой памяти. И массив там работает именно как массив, а не как указатель, по умному называется flexible array: https://gcc.gnu.org/onlinedocs... ero-Length

Правда в документации они немного недоописали, ещё их используют и так:

C
struct s
{
  int len;
  int arr[];
};
 
struct s *p1, *p2, *p3;
 
p1 = malloc (sizeof (struct s) + 2 * sizeof (int));
p1->len = 2;
p1->arr[0] = 10;
p1->arr[1] = 20;
 
p2 = malloc (sizeof (struct s) + 3 * sizeof (int));
p2->len = 3;
p2->arr[0] = 30;
p2->arr[1] = 40;
p2->arr[2] = 50;
 
p3 = malloc (sizeof (struct s) + 5 * sizeof (int));
p3->len = 5;
p3->arr[0] = 60;
p3->arr[1] = 70;
p3->arr[2] = 80;
p3->arr[3] = 90;
p3->arr[4] = 100;
А далее подобное можно подсовывать в функции типа:

C
void foo (struct s *p)
{
  for (i = 0; i < p->len; i++)
    x = p->arr[i];
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
18.10.2014, 19:03
Цитата Сообщение от kravam Посмотреть сообщение
В объекте этого типа должно храниться как минимум три указателя: (на конструктор, не деструктор и на конструктор копирования), это уже 12 байт. В общем, спасибо, кто откликнется.
Вы находитесь в плену заблуждения о том, что в объектах класса якобы хранятся указатели на методы класса. В реальности же в объектах класса никогда не хранятся никакие указатели ни на какие методы.

Если вы объявите и используете некий класс 'S', как в примере ниже

C++
1
2
3
4
5
6
7
8
9
struct S {
  int x;
  void foo() { x = 5; }
};
 
int main() {
  S s;
  s.foo();
}
то компилятор внутренне интерпретирует 'S::foo', как совершенно самостоятельную функцию с дополнительным скрытым параметром 'this'. Т.е. вышеприведенный код будет фактически внутренне интерпретирован как следующий эквивалентный чисто Си-шный код

C++
1
2
3
4
5
6
7
8
9
10
11
12
struct S {
  int x;
};
 
void s$foo(S* this) { 
  this->x = 5; 
}
 
int main() {
  S s;
  s$foo(&s);
}
т.е. до тех пор, пока вы работаете с обычными (невиртуальными) методами, все эти методы являются не более чем чисто синтаксической шелухой (то, что по-английски называют syntactic sugar - синтаксический сахар), т.е. просто альтернативной формой записи, не привносящей абсолютно ничего принципиально нового по сравнению с обыкновенными структурами и функциями языка С. Никаких указателей "на конструкторы, деструкторы и операторы" или какие-либо еще методы в объекте нет и никогда не было.

(Более того, первые компиляторы языка С++ работали именно путем буквальной трансляции С++ кода в С код так, как я показал выше. И язык С++ изначально разрабатывался именно с оглядкой на такой метод трансляции С++ программ.)

Какие-то особенности ("указатели" и т.п.) начинаются только тогда, когда вы начинаете использовать виртуальные методы (и/или виртуальное наследование). При этом внутри класса действительно появляются скрытые указатели. Но и это будут не указатели на индивидуальные виртуальные методы, а единственный указатель на виртуальную таблицу. (При множественном наследовании в классе может оказаться более одного указателя на виртуальную таблицу, но это уже другая песня.)

Добавлено через 5 минут
Цитата Сообщение от Tulosba Посмотреть сообщение
гэ-цэ-цэшечка:
C++
1
2
3
4
struct S
{
    int i[];
};
"Гэ-цэ-цэшечка" врет сразу на двух уровнях.

Во-первых, в языке С++ запрещено объявление массивов неизвестного размера как нестатических членов классов.

Во-вторых, даже в языке С (откуда эта фича позаимствована) запрещается использовать такое объявление в качестве единственного поля структуры. Структура обязана содержать как минимум одно поле перед таким массивом.

Добавлено через 2 минуты
Цитата Сообщение от p_r_a_g_m_a Посмотреть сообщение
Я к тому, что int i[] по идее должен быть тоже равен (как и int* i) 4-8
Это почему? Массивы в языках С и С++ указателями не являются и потому ожидать, что массив привносит в размер класса нечто "как и int*" было бы странным.

Добавлено через 7 минут
Цитата Сообщение от Evg Посмотреть сообщение
Правда в документации они немного недоописали, ещё их используют и так
То, что вы прочитали в документации по ссылке рассказывает о нестандартных свойствах компилятора GCC.

А что касается объявлений массивов вида 'int i[]' в конце структуры, то их не "используют и так", а используют именно так. Весь смысл объявления массива типа 'int i[]' в конце структуры заключается именно в том, чтобы потом выделить правильное количество памяти под конкретный размер массива через 'malloc'. Для того эта возможность в язык и была введена.

Альтернативные способы использования этой возможности, наверное, можно изобрести, но то, что приведено по ссылке

C
1
2
3
struct f1 {
       int x; int y[];
     } f1 = { 1, { 2, 3, 4 } };
является опять же расширением GCC. Язык С такого использования не допускает.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
18.10.2014, 23:18
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
То, что вы прочитали в документации по ссылке рассказывает о нестандартных свойствах компилятора GCC
А разве с этим кто-то спорил?

Добавлено через 2 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
то их не "используют и так", а используют именно так
С учётом примера, приведённого тобою же в конце твоего поста, очевидно, что это не так. Если ты их используешь только для того, чтобы работать через malloc, из этого никак не следует, что это единственный способ использования flexarray'ев
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
19.10.2014, 00:06
Цитата Сообщение от Evg Посмотреть сообщение
С учётом примера, приведённого тобою же в конце твоего поста, очевидно, что это не так.
Не совсем понимаю, как это может быть "очевидно" из данного примера. Данный пример, как я сказал выше, не имеет никакого отношения к языку С, а является лишь одним из развеселых нестандартных расширений компилятора gcc.

Цитата Сообщение от Evg Посмотреть сообщение
Если ты их используешь только для того, чтобы работать через malloc, из этого никак не следует, что это единственный способ использования flexarray'ев
Я говорю лишь об использовании таких массивов в стандартном языке С. Техника "struct hack" (а именно так она устойчиво называется) - это целая легенда в истории языка С. Основана она именно на run-time выделении памяти ('malloc' и т.п., разумеется никто вам не мешает написать свой аллокатор). И именно для поддержки приема "struct hack" в язык были введены flexible arrays.

Если вы умеете как-то использовать flexible arrays по-другому в языке С - я весь внимание.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
19.10.2014, 12:18
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Данный пример, как я сказал выше, не имеет никакого отношения к языку С, а является лишь одним из развеселых нестандартных расширений компилятора gcc
Как-то мне это напоминает ситуацию, когда сидят люди, обсуждают нарисованный зелёный круг, кто-то приходит и говорит "вы нифига не шарите, тут нарисован зелёный круг, а если кто-то считает, что тут красный квадрат - прошу мне это доказать"
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
19.10.2014, 12:18
Помогаю со студенческими работами здесь

Как sizeof считает размер?
Есть код программы. Скажите как определить размерность структуры? Дело в том что выдает 4 байта, но хотелось бы узнать как это делает...

Возращение типа данных без sizeof
Нужно описать функцию sizeof, как это сделать?

Является ли оператор sizeof синтаксическим сахаром над System.Runtime.InteropServices.Marshal.SizeOf?
Является ли оператор sizeof синтаксическим сахаром над System.Runtime.InteropServices.Marshal.SizeOf?

Sizeof(.) или constexpr size_t tmp = sizeof(.)
sizeof(...) или constexpr size_t tmp = sizeof(...) Как лучше с точки зрения производительности? правильности?

Как вставить знак охраны авторского права © в строку?
Никак не могу понять, как вставить знак охраны авторского права в строку. Например есть код: QMessageBox::information(this, ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru