LINUX.ORG.RU

sizeof(class A) ?


0

1

x86, 32bit, почему sizeof(class A) = 1 ?
(возможно смешно, но тем не менее)

#include <stdio.h>
class A 
{
public: 
  A(); 
 ~A(); 
};
int main(void)
{
   printf("sizeof(class A) = %d \n", sizeof(class A)); 
   printf("sizeof(A) =%d \n", sizeof(A)); 
   printf("sizeof(int)=%d \n", sizeof(int));
  printf("sizeof(void)=%d \n", sizeof(void));
  printf("sizeof(void*)=%d \n", sizeof(void*));
}
$ g++ t.cpp
$ ./a.out 
sizeof(class A) =1 
sizeof(A) =1 
sizeof(int)=4 
sizeof(void)=1 
sizeof(void*)=4 
$

А сколько тебе надо?

А как насчет std::vector<A>, если sizeof(class A) равен 0?

AF ★★★
()

По стандарту размер чего угодно должен быть >= 1. Например чтобы можно было сделать указатель на это что-то.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от slovazap

Ага, а теперь расскажи нам какой размер у void.

Вот только new void() сделать нельзя, да.

psikh
()
Ответ на: комментарий от slovazap

Ага, а теперь расскажи нам какой размер у void.

gcc и clang считают, что 1 байт

wota ★★
()
Ответ на: комментарий от slovazap
del@del-lmde:~$ gcc -Wall -Wextra testvoid.c -o testvoidc
del@del-lmde:~$ ./testvoidc 
1
del@del-lmde:~$ cat testvoid.c
#include <stdio.h>

int main() {
    printf("%zu\n", sizeof(void));
    return 0;
}

В плюсах тоже самое, но там будет ещё вроде ворнинг про то, что к void нельзя применять sizeof. Вообще void - это отдельная тема. Я говорил про всё остальное, включая пользовательские типы.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

Тема была не про void - помните ?
можно порыться в заголовочных файлах
/usr/include/c++/4.5.1/

#include <stdio.h>
struct zero
{};
int main(void)
{ printf("sizeof(struct zero)=%d \n", sizeof(struct zero));
  printf("sizeof(void)=%d \n", sizeof(void));
  return 0;
}

$ gcc t_zero.c && ./a.out 
sizeof(struct zero)=0 
sizeof(void)=1 
$ g++ t_zero.c && ./a.out 
t_zero.c: In function ‘int main()’:
t_zero.c:12:43: warning: invalid application of ‘sizeof’ to a void type
sizeof(struct zero)=1 
sizeof(void)=1 
$

Написал вопрос так как просто поставило в тупик.
Не могу найти объяснение
В с++ всё типы - классы и базовые(int,char,double,...) так-же.
что то добавляется компилятором в код,
при создании наследуется базовый класс типов ?
найти представление базового класса int не удалось
вопрос остаётся открытым.

user209
() автор топика
Ответ на: комментарий от user209

есть ещё ссылка
http://stackoverflow.com/questions/9439240/sizeof-class-with-int-function-vir...
но там не даётся ответ на вопрос, просто констатация факта
раньше где то читал, что оператор sizeof() нельза применять
к собственным типам данных, но где читал не помню, не могу найти, не помню верно ли это, читал ли
почему sizeof(class A) =1 ?

Ещё вопрос:
как представляются функции класса ?
class A
{ A(); // <-
~A(); // <-
};
Любое имя функции - это адресс смещения в программе
class A { }; - это область видимости
A::A()- ведь не указатель на функцию, иначе был бы размер
А как представить ?

может sizeof()-оператор переопределённый в базовом классе,
который наследуется при определении нового типа ?
Одни вопросы.

user209
() автор топика

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

AGUtilities ★★★
()
Ответ на: комментарий от user209

http://stackoverflow.com/questions/6899886/sizeof-empty-class/6899935#6899935 чем недостаточен коментарий Konrad Rudolph ?

ещё более развёрнуто http://stackoverflow.com/questions/6899886/sizeof-empty-class/6899927#6899927

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

qulinxao ★★☆
()
Ответ на: комментарий от user209

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

если методы виртуальные то по vtable содержимому

кури стандарты

/thread

qulinxao ★★☆
()
Ответ на: комментарий от slovazap

Ага, а теперь расскажи нам какой размер у void.

UB

drBatty ★★
()
Ответ на: комментарий от DELIRIUM

Я говорил про всё остальное, включая пользовательские типы.

понятия «размер» для твоего класса не имеет смысла. Пруфы у Екклесиаста, ибо чего нет, то нельзя считать.

drBatty ★★
()
Ответ на: комментарий от drBatty

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

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

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

дык как можно взять «адрес» объекта, которого не существует? В C++ нет понятия «указатель на код объекта», а раз нет указателя, его и нельзя брать. Проблема в том, что код есть у класса, и он общий для всех объектов этого класса, и становится персональным только при наличии хоть каких-то персональных данных объекта. Ну а ежели таких данных нет, то нет и объекта (только в статическом смысле).

Т.е. код

class A 
{
public: 
  A(); 
 ~A(); 
}a, b;
НЕ порождает объект a, хотя кажется, что такой объект есть. Но этот «объект» на самом деле совершенно не отличим объекту b, и потому не имеет никакого адреса, и никакого размера.

drBatty ★★
()
Ответ на: комментарий от drBatty

Што?

#include <iostream>
#include <iomanip>

class A {
    public:
    A() {}
    ~A() {}
};

int main() {
    A a, b;
    std::cout << std::hex << "a: 0x" << &a
              << "\nb: 0x" << &b << std::endl;
}
$ ./test_empty 
a: 0x0x7fff7b25c64f
b: 0x0x7fff7b25c64e

И пройдись уже по ссылкам

The runtime just marks the one byte as occupied so that no other object will be allocated at its position. But there isn’t anything “held” there to occupy the byte.

The only reason for this rule is that objects must be uniquely identifiable. An object is identified by the address it has in memory. To ensure that no two objects have the same address (except in the case of empty-base class optimisation), objects of empty classes “occupy” memory bu having a non-zero size.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от drBatty
#include <iostream>
#include <iomanip>
#include <string>
int c;
class A;
A* tbl[3];
class A {
public: 
  A(){
  	tbl[c++]=this;
  	
  }; 
 
 std::string WhoAmI(){
 	if(this==tbl[0]) return "I am A";
  	return "I not A so probabli B :)"; 
  	}
};





int main(){
	A a;
	A b;

	std::cout<<a.WhoAmI()<<std::endl;
	
        std::cout<<b.WhoAmI()<<std::endl;

	return 0;

}

ой что это .

неакуратный код показывающий различимость пустых обьектов

ps. спасибо DELIRIUM за исходный пример

qulinxao ★★☆
()
Ответ на: комментарий от DELIRIUM

The only reason for this rule is that objects must be uniquely identifiable. An object is identified by the address it has in memory. To ensure that no two objects have the same address (except in the case of empty-base class optimisation), objects of empty classes “occupy” memory bu having a non-zero size.

ну кагбэ про это я и говорил: объекта физически не существует, но в стандарт добавили костыль, для того, что-бы быдлокодеры могли отличить твои A::a и A::b. Вот только я не совсем понимаю, _зачем_ тебе такие объекты IRL? А особенно непонятен конструктор A::A() и деструктор A::~A() которые конструируют и уничтожают ничто? Особенно неясна функция деструктора, который даже перезагрузить нельзя, ибо он не виртуальный, и следовательно не станет вызываться в производном классе?

drBatty ★★
()
Ответ на: комментарий от qulinxao

неакуратный код показывающий различимость пустых обьектов

вообще-то этот код показывает различимость указателей, которые ты объединил в массив. Т.е., то, что a[0] != a[1]. Ну и что? Например NULL неотличимо от NULL, и тем не менее, a[0] и a[1] это разные вещи, даже если их значение NULL.

drBatty ★★
()
Ответ на: комментарий от drBatty

читай код ...

для потребителя есть переменные а и б - чьё поведение различимо при этом

то что реализация такова - это частность

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

qulinxao ★★☆
()
Ответ на: комментарий от DELIRIUM

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

интересно, как это сделано ?
При создании пользовательского типа создаётся тип,
который наследует код, содержащий ... ?
Можно ли это увидеть в заголовочных файлах ?
например, как в с++ представлен базовый тип данных 'int' ?

user209
() автор топика
Ответ на: комментарий от user209

интересно, как это сделано ?

это хорошо видно на примере Gtk+ (структуры и функции с первым параметром-указателем на эти структуры)

При создании пользовательского типа создаётся тип,
который наследует код, содержащий ... ?

если не указывать что наследовать, то просто создаётся новый класс. если указывать, то наследуется тот класс что указан. почитай ещё про шаблоны в с++ (templates).

Можно ли это увидеть в заголовочных файлах ?

как и в C, в C++ заголовочные файлы используются для определения «открытых» API — если в них есть, значит можно; но это не как в языках высшего уровня (Python, Java) — нельзя определить все имена типов/классов/etc

например, как в с++ представлен базовый тип данных 'int' ?

в общем виде так и представлен (в зависимости от таргета компилятора)

AGUtilities ★★★
()
Последнее исправление: AGUtilities (всего исправлений: 2)
Ответ на: комментарий от user209

С++ это единсвенный язык созданый одним человеком(Страустропом) обладающий всеми достоинствами разработки комитетом(чейто перефраз)

курни историю(на лурке наверно) С++ изначально пропатченый специфичным сознанием Страустропа(прикручивание по мотивам смолтока?) препроцессор над С - компромисс возможностей .

так как те ограничения теперь не так актуальны более адекватна для разработки крупными колективами модель Objective-C у которой много жирнее в сравнении с С++ рантайм.

зы. int в с++ это строка бит длины кратной длине базового (char/byte) как и в С

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.