Получение размера переменной-члена

#c #c 11

#c #c 11

Вопрос:

Если существует структура POD с некоторыми переменными-членами, например, такими:

 struct foo
{
   short a;
   int b;
   char c[50];
   // ...
};
  

Есть ли способ получить размер переменной-члена в байтах, не создавая объект этого типа?

Я знаю, что это сработает:

 foo fooObj;
std::cout << sizeof( fooObj.a ) << std::endl;
std::cout << sizeof( fooObj.b ) << std::endl;
std::cout << sizeof( fooObj.c ) << std::endl;
  

Будет ли следующее оптимизировано компилятором и предотвратит создание объекта?

 std::cout << sizeof( foo().a ) << std::endl;
  

Комментарии:

1. Если они не являются статическими, я так не думаю…

2. Каковы точные требования? Почему вы не можете использовать информацию о времени компиляции? В моем понимании, C не использует динамическую генерацию классов и манипулирование ими

Ответ №1:

Вы можете сделать это в C 0x:

 sizeof(foo::a);
  

Ответ №2:

5.3.3/1:

Оператор sizeof выдает количество байтов в объектном представлении его операнда. Операндом является либо выражение, которое не вычисляется, либо заключенный в скобки идентификатор типа.

Вышесказанное означает, что следующая конструкция четко определена:

 sizeof( ((foo *) 0)->a);
  

Комментарии:

1. @Martin: Но он пишет макрос, вы бы сказали «Слишком много работы, и это скрывает фактический смысл». : P

2. @Nawaz: Но на основе приведенного выше стандарта. Исходные комментарии OP сохранены, sizeof(foo().a) действительны, четко определены, объект не сконструирован, не является уродливым и не требует дополнительной работы с макросом, который может ввести в заблуждение.

3. @Martin: Что? foo() не создает объект, даже будь это анонимный объект?

4. @Nawaz: Нет, не в этом случае, операнд sizeof не вычисляется.

5. @Erik: Потрясающе. Как получилось, что я это пропустил.

Ответ №3:

Вместо этого используйте эту форму: sizeof(foo::a) .

Ответ №4:

Используйте очевидный:

 sizeof( foo::a )
  

В C sizeof ВСЕГДА вычисляется во время компиляции, поэтому никаких затрат на выполнение не требуется.

Комментарии:

1. Это работает 🙂 он просто ссылается на элемент внутри определения класса.

2. @Nawaz А? Какое отношение к этому имеет static?

3. @unapersson: Вы обращаетесь к a тому, который является нестатическим членом foo .

4. Я должен отметить, что некоторое время назад я переключился на компиляцию своего кода с c 0x. Может быть, нам здесь нужны два тега C ?

5. @Space_C0wb0y Но sizeof( foo::a ) не работает для текущей версии c . Это работает для c 0x

Ответ №5:

C -0x позволяет это сделать:

   std::cout << sizeof( foo::a ) << std::endl;
  std::cout << sizeof( foo::b ) << std::endl;
  std::cout << sizeof( foo::c ) << std::endl;
  

C -0x позволяет sizeof работать с членами классов без явного объекта.

Статья находится здесь: Расширение sizeof для применения к нестатическим элементам данных без объекта (редакция 1)

Я увидел сообщение об этом выше слишком поздно. Извините.

Ответ №6:

Вы можете создать оболочку макроса из того, что @Erik предложил как:

 #define SIZE_OF_MEMBER(cls, member) sizeof( ((cls*)0)->member )
  

А затем использовать его как:

 cout << SIZE_OF_MEMBER(foo, c) << endl;
  

Вывод:

 50
  

Демонстрация:http://www.ideone.com/ZRiMe

Комментарии:

1. Слишком много работы, и это скрывает фактический смысл. По крайней мере, дайте макросу имя, которое объясняет, что он делает.

2. @Martin: Я не нашел никакого убедительного имени для макроса. Предложите мне один. 🙂

3. SIZE_OF_MEMBER, вот что она сказала.

4. Все еще предстоит много работы. Но, по крайней мере, теперь имя выделяется.

5. используйте: sizeof(foo().a) или sizeof(foo::a)

Ответ №7:

 struct foo
{
   short a;
   int b;
   char c[50];
   // ...
   static const size_t size_a = sizeof(a);
   static const size_t size_b = sizeof(b);
   static const size_t size_c = sizeof(c);
};
  

Использование:

 foo::size_a
  

Комментарии:

1. Это сработало бы, но было бы PITA, потому что для этого потребовалось бы добавить 10 дополнительных статических переменных

2. sizeof не приводит int , оно выдает std::size_t .

3. @iammilind : К сожалению, я не был отрицательным голосованием. ;-]