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

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

18.10.2014, 13:32. Показов 2432. Ответов 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
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
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
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
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
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
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
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
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
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,178
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
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,178
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
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru