Author |
Topic: Memory in C++ (Read 1581 times) |
|
puzzlecracker
Senior Riddler
Men have become the tools of their tools
Gender:
Posts: 319
|
|
Memory in C++
« on: Jan 18th, 2005, 10:17am » |
Quote Modify
|
How much bytes of memory will structs below take on 32 bit machine? What about 64 bit machine? Why is it different? (if it's relevent, use standard size of datatypes) a) Code: struct { short int a; int b; }; |
| b) Code: struct{ short int a; int b; int somefunc(); virtual int func1(); }; |
| c) Very Tricky (Hint: it is tricky with virtual function (or should I say pointers to vtable...you should know something about vtables in last but clever case)) Code: struct{ short int a; int b; virtual int func_1(); virtual int func_2(); : : virtual int func_n(); }; |
|
|
« Last Edit: Jan 18th, 2005, 10:19am by puzzlecracker » |
IP Logged |
While we are postponing, life speeds by
|
|
|
towr
wu::riddles Moderator Uberpuzzler
Some people are average, some are just mean.
Gender:
Posts: 13730
|
|
Re: Memory in C++
« Reply #1 on: Jan 18th, 2005, 1:05pm » |
Quote Modify
|
:: assuming int has size of 4, which it needn't have (Short int has size two, long int has size 4, how int is interpreted is up to the compiler afaik) a 2+4=6 b 2+4+4+4=14 * c 2+4+4=10 * *) there's additional space outside the struct for the vtable, I'd assume 4 bytes per virtual function on 64 bits machine it might be, but the same cautionary about int applies. It makes sense to assume it's the size of one machine word, but I don't think the standard defines it. To get 8 bytes use long long int. a 2+8=10 b 2+8+8+8=26 * c 2+8+8=18 * *) again additional space outside the struct for a vtable ::
|
|
IP Logged |
Wikipedia, Google, Mathworld, Integer sequence DB
|
|
|
puzzlecracker
Senior Riddler
Men have become the tools of their tools
Gender:
Posts: 319
|
|
Re: Memory in C++
« Reply #2 on: Jan 18th, 2005, 3:42pm » |
Quote Modify
|
>assuming int has size of 4, which it needn't have (Short int >has size two, long int has size 4, how int is interpreted is up >to the compiler afaik) >a 2+4=6 >b 2+4+4+4=14 * >c 2+4+4=10 * I think a)8 b/c machine is block is 4bytes on 32 bit architecture and we cannot put int on the same block as short therefore we need 2 blocks, padding is added to the first block b) 16 based on the same reasoning (not taking vtable into account) c) 12 >on 64 bits machine it might be, but the same cautionary >about int applies. It makes sense to assume it's the size of >one machine word, but I don't think the standard defines it. >To get 8 bytes use long long int. >a 2+8=10 >b 2+8+8+8=26 * >c 2+8+8=18 * short is 2 int is 4 bytes and a pointer is 8 byte on 32 bit architecture 64-bit machine likes to fetch at every 8 bytes; and assume a short int is either 16 or 32 bits. a) 8 (2 and 4 fit on the same block) -since short int is 2 bytes and int is 4 bytes, it will occupy a block of 8 byte, so the total size is 8 byte. b)24 (1st block: 2 + 4 )+(2nd block: 8 ) + (3rd block: =24 c) 16 based on b ============ Is my reasoning correct? ==== Please let me know if I solved these ones correctly. thx >struct A >{ > char c; >short int si; > int j; > char d > int i; >}; 32 bit machine: ----------------- 1st block: s, si +padding = 4 bytes 2nd block: j = 4 bytes 3rd block: d+padding = 4 bytes 4th block: i = 4 bytes ----------------------------------- TOTAL: = 16 bytes 64 bit Machine ---------------- 1st block: s,si j+d = 8byte 2nd block i+padding = 8byte ------------------------------ TOTAL: 16 bytes 2) >struct B >{ > int i; > short int si; > char c; > char d; > int j; >}; 32 bit machine -------------- 1st block: i = 4 bytes 2rd block: s1, c d = 4 bytes 4th block j = 4 bytes ----------------------------------- TOTAL: 12 bytes 64 bit Machine ---------------- 1st block: i, si c + d = 8 byte 2nd block j = 8 byte --------------------------------- TOTAL: = 16 bytes ========================================================= small question: virutal functions, regular fucntions and inline functions take the same space (ex: 4 bytes or 8 bytes 32 and 64 bits respectively)? According to alignement rules: compiler is tring to fit as many variable (data types) as possible in each block for as long as it fits entirely or else adds padding... is that the correct way of thinking? also, is function always represented as a pointer in a struct and occupies its size? Thanks... ...Puzzlecracker!
|
« Last Edit: Jan 18th, 2005, 4:05pm by puzzlecracker » |
IP Logged |
While we are postponing, life speeds by
|
|
|
towr
wu::riddles Moderator Uberpuzzler
Some people are average, some are just mean.
Gender:
Posts: 13730
|
|
Re: Memory in C++
« Reply #3 on: Jan 19th, 2005, 12:46am » |
Quote Modify
|
on Jan 18th, 2005, 3:42pm, puzzlecracker wrote: I think a)8 b/c machine is block is 4bytes on 32 bit architecture and we cannot put int on the same block as short |
| You seem to be right, at least as far as g++ is concerned. Quote:short is 2 int is 4 bytes |
| I can only reiterate that I'm pretty sure the size of an int is not defined by the c++ ansi standard. It used to be 16 bits, equal to a short int, which is btw defined as 16 bits and that shouldn't change on another architecture (that would seriously screw up any semblance of compatibility, not that that's great anyway.). I don't see a reason why int wouldn't be upgraded to 64 bits on 64-bit machines, it's only natural to use the machine-word if the datasize isn't specified. There's probably padding to the largest datatype-size here as well. Quote:Please let me know if I solved these ones correctly. thx |
| There is one good way to find out: try it! Quote:small question: virtual functions, regular fucntions and inline functions take the same space (ex: 4 bytes or 8 bytes 32 and 64 bits respectively)? |
| The point of an inline function, is that it works sort of like a macro; wherever you call it, in the ideal case, the call is replaced by the body of the function. Of course sometimes the compiler notices that's impossible, in which case it ignores the 'inline' keyword and you have a normal function. In the other two cases you simply have a pointer. Quote:According to alignement rules: compiler is tring to fit as many variable (data types) as possible in each block for as long as it fits entirely or else adds padding... is that the correct way of thinking? |
| I'm not sure. If it is, I don't see why the compiler wouldn't reorganise the order of elements in a struct to optimize memory usage. (So struct A would take 12 i.s.o. 16 bytes, by moving char d next to char c) Quote:also, is function always represented as a pointer in a struct and occupies its size? |
| I'm not sure what you mean by 'occupies its size'.
|
|
IP Logged |
Wikipedia, Google, Mathworld, Integer sequence DB
|
|
|
puzzlecracker
Senior Riddler
Men have become the tools of their tools
Gender:
Posts: 319
|
|
Re: Memory in C++
« Reply #4 on: Jan 19th, 2005, 6:49am » |
Quote Modify
|
Quote:also, is function always represented as a pointer in a struct and occupies its size? I'm not sure what you mean by 'occupies its size'. |
| in a struct: how much memory a regular function occupy? illustrate the usage of sizeof operator.. .thx
|
« Last Edit: Jan 19th, 2005, 7:09am by puzzlecracker » |
IP Logged |
While we are postponing, life speeds by
|
|
|
towr
wu::riddles Moderator Uberpuzzler
Some people are average, some are just mean.
Gender:
Posts: 13730
|
|
Re: Memory in C++
« Reply #5 on: Jan 19th, 2005, 7:37am » |
Quote Modify
|
on Jan 19th, 2005, 6:49am, puzzlecracker wrote:in a struct: how much memory a regular function occupy? |
| In the struct there's only a pointer to the function, the actual function lies outside the struct. (Since a struct is a datatype, and a function is, euhm, data, static data even, I'd say.) Quote:illustrate the usage of sizeof operator.. .thx |
| struct {int a, char b, int c} x; cout << sizeof(x) << endl ; /* should give 12 (apparantly ;) */ btw, 'sizeof' isn't really an operator, I think it's a macro. In any case its result is available at compiletime, so just precompiling a file should be able to give you your answer as well.
|
|
IP Logged |
Wikipedia, Google, Mathworld, Integer sequence DB
|
|
|
puzzlecracker
Senior Riddler
Men have become the tools of their tools
Gender:
Posts: 319
|
|
Re: Memory in C++
« Reply #6 on: Jan 19th, 2005, 8:04am » |
Quote Modify
|
I've just done a little bit of research. Apparently, function declaration in a struct doesn't occupy anything, contrary to my intuitive assumption that it occupies a pointer. Actually, in function declaration there is a pointer to a struct.... maybe somewhat similar to 'this' pointer.
|
|
IP Logged |
While we are postponing, life speeds by
|
|
|
towr
wu::riddles Moderator Uberpuzzler
Some people are average, some are just mean.
Gender:
Posts: 13730
|
|
Re: Memory in C++
« Reply #7 on: Jan 19th, 2005, 8:19am » |
Quote Modify
|
hmm, yes, that makes sense.. It's easy to confuse functions and pointers to them. You can of course have function pointers in a struct: struct{ int a; int (* somefunc) (int); /* function pointer*/ }; Anyway, it's worth considering that originally C++ was just a preprocessor for C, and classes were basicly just structs (and still are in a sense). So the this-pointer you get with a function declared in a struct is the same as the this-pointer you get with a function declared in a class.
|
|
IP Logged |
Wikipedia, Google, Mathworld, Integer sequence DB
|
|
|
puzzlecracker
Senior Riddler
Men have become the tools of their tools
Gender:
Posts: 319
|
|
Re: Memory in C++
« Reply #8 on: Jan 19th, 2005, 3:13pm » |
Quote Modify
|
well, I am treating structs in a sense of class.... that is why I had,(in fact still do) some confusion as to how memory is aligned.
|
|
IP Logged |
While we are postponing, life speeds by
|
|
|
John_Gaughan
Uberpuzzler
Behold, the power of cheese!
Gender:
Posts: 767
|
|
Re: Memory in C++
« Reply #9 on: Jan 21st, 2005, 8:19pm » |
Quote Modify
|
on Jan 19th, 2005, 8:04am, puzzlecracker wrote:I've just done a little bit of research. Apparently, function declaration in a struct doesn't occupy anything, contrary to my intuitive assumption that it occupies a pointer. Actually, in function declaration there is a pointer to a struct.... maybe somewhat similar to 'this' pointer. |
| In C++, structs and classes are identical except for default member visibility (public v private). Functions inside classes and structs are located outside, but have an implicit pointer (this) to the data structure. This is a tough concept for OO programmers new to C++, for example, people familiar with Java. All of these OO concepts are enforced at compile-time, not run-time. In the end, these are just functions, pointers, and other junk on the stack. In ASM, variables (scalar or composite) are just offsets on the stack or into a heap. There is no concept of "classes contain functions," because code and data are separate. Anyway, there is no guarantee about struct alignment unless you specify it on the command-line. That being said, a reasonable assumption is that members will be aligned on word boundaries (e.g. 4 bytes on a 32 bit machine, 8 bytes on a 64 bit machine). This is because memory accesses tend to be faster this way, definitely on x86, but also on other platforms to a lesser extent.
|
|
IP Logged |
x = (0x2B | ~0x2B) x == the_question
|
|
|
puzzlecracker
Senior Riddler
Men have become the tools of their tools
Gender:
Posts: 319
|
|
Re: Memory in C++
« Reply #10 on: Jan 22nd, 2005, 9:29am » |
Quote Modify
|
The kink in the word boundary lies in data such as char or short int - will 2 short char occupied in one block (let s say 4 bytes long) or separate.... same goes for combination of short int and char, char and char, int and char etc... Here is puzzling example We have 64 bit machine that is each block is 8 byte long. More precisely, a machine cans 8 byte long bytes at a time So for struct{ short int a, b; virtual int func(); }; Would the size be 8 or 16 for it can package it all in one block?
|
|
IP Logged |
While we are postponing, life speeds by
|
|
|
Margit
Guest
|
I'll throw in a few more (a) struct A { unsigned int a:1; long double b; } (b) I think only in GNU C struct B { int a; char b[0]; } (c) struct C { int a; char b[]; } What's the difference between (b) and (c) ? Referring to (a) above (d) struct D { int d; struct A e; }
|
|
IP Logged |
|
|
|
gniv
Newbie
Gender:
Posts: 19
|
|
Re: Memory in C++
« Reply #12 on: Feb 3rd, 2005, 6:10pm » |
Quote Modify
|
Here are the results using gcc on an x86 (32 bit) machine: For the original questions: :: a: 8, b: 12, c: 12 :: This is as expected. For the questions posed by Margit: :: a: 16, b: 4, c: 4, d: 20:: This was a surprise to me (for b and c). For this structure: struct{ short int a, b; virtual int func(); }; the result is :: 8 :: PS. You can eliminate padding in gcc by adding the following after the struct/class definition (before semicolon): __attribute__((packed))
|
« Last Edit: Feb 3rd, 2005, 6:15pm by gniv » |
IP Logged |
|
|
|
igni_ferroque
Newbie
Posts: 11
|
|
Re: Memory in C++
« Reply #13 on: Feb 4th, 2005, 9:04pm » |
Quote Modify
|
Quote:I can only reiterate that I'm pretty sure the size of an int is not defined by the c++ ansi standard. |
| You are correct. Quote:I don't see a reason why int wouldn't be upgraded to 64 bits on 64-bit machines, it's only natural to use the machine-word if the datasize isn't specified. |
| Usually long integers and pointers are 64-bits.
|
« Last Edit: Feb 4th, 2005, 9:08pm by igni_ferroque » |
IP Logged |
|
|
|
Grimbal
wu::riddles Moderator Uberpuzzler
Gender:
Posts: 7527
|
|
Re: Memory in C++
« Reply #14 on: Feb 7th, 2005, 4:10am » |
Quote Modify
|
You mean: long long int have 64 bits, don't you? I am used to long int having 32 bits, short int having 16 bits, and int being either of them. I guess int would be 64 bits on machines that use 64 bit memory addresses. I have never used one.
|
|
IP Logged |
|
|
|
igni_ferroque
Newbie
Posts: 11
|
|
Re: Memory in C++
« Reply #15 on: Feb 7th, 2005, 10:36am » |
Quote Modify
|
Most systems use the ILP32 model (for 32-bit modes) or the LP64 model (for 64-bit modes). ILP32 means Integers, Long integers, and Pointers all are 32-bits. In LP64 models, Integers are 32-bits and long integers and Pointers are 64-bits. Short integers are usually 16 bits. Long long is a nonstandard type that is "at least as long" as a long integer. On my Mac (G4) under gcc and on my UltraSPARC box, long long is 64-bits wide.
|
« Last Edit: Feb 7th, 2005, 10:38am by igni_ferroque » |
IP Logged |
|
|
|
John_Gaughan
Uberpuzzler
Behold, the power of cheese!
Gender:
Posts: 767
|
|
Re: Memory in C++
« Reply #16 on: Feb 7th, 2005, 2:13pm » |
Quote Modify
|
According to section 3.9.1 of ISO14882-2003 (C++ 2003 standard): "There are four signed integer types: 'signed char', 'short int', 'int', and 'long int.' In this list, each type provides at least as much storage as those preceding it in the list. Plain ints have the natural size suggested by the architecture of the execution environment39)" "39) that is, large enough to contain any value in the range of INT_MIN and INT_MAX, as defined in the header <climits>." So, the standard basically says nothing about integral types except that as you go to "bigger" types they really are just in non-decreasing order. It says something similar about the three floating point types. Typically a char is 8 bits, short int and wchar_t are 16 bits, int/long int are 32 bits, long long int(GNU)/int64(MSVC) and pointers are 64 bits. This is only on x86, however. I have seen 36 bit ints and longs, 18 bit shorts, and 10 bit chars before. That was on a mainframe. This is also why "configure" scripts in Unix usually check the size of integral types and write them to a config.h file: you cannot depend on a particular size, even if most implementations are consistent.
|
|
IP Logged |
x = (0x2B | ~0x2B) x == the_question
|
|
|
John_Gaughan
Uberpuzzler
Behold, the power of cheese!
Gender:
Posts: 767
|
|
Re: Memory in C++
« Reply #17 on: Feb 7th, 2005, 2:18pm » |
Quote Modify
|
on Feb 7th, 2005, 10:36am, igni_ferroque wrote:Long long is a nonstandard type that is "at least as long" as a long integer. On my Mac (G4) under gcc and on my UltraSPARC box, long long is 64-bits wide. |
| This is a shame, really. I wish whomever set the de facto standard for x86 compilers would have used 'long int' for 64 bit integers. Maybe this was because back in the day x86 couldn't do 64 bits. It took creative use of the MMX registers to implement 64 bit integers. Now with ia64 and amd64 we have native 64 registers, but 'long int' is still 32 bits in every compiler I have seen. On top of that, we have at least two non-standard 64 bit integer types, 'long long int' in GCC and 'int64' in MSVC.
|
|
IP Logged |
x = (0x2B | ~0x2B) x == the_question
|
|
|
|