An int that is 4 bytes in native, and 12 bytes in .NET? Huh?

B

BogusException

Why is it that VS 2005, VC++.NET needs 12 bytes to store an int, when
it can be done natively with 4? Mind you, even on 64-bit systems the
int is still supposed to be 4 bytes. An yes, the _pointer_ will be 8
bytes on a 64 bit system versus 4 bytes on a 32 bit one.

So what gives?

Consider:

The two listings below came from compiling the following console
application with VS6.0 and VS2005 on a/the same 32 bit system:

1. void main(){
2. int x=2;
3. int y=5;
4. int z=0;
5. z=x+y;
6. }

Looking below, the first listing shows each int being stored at 4 byte
intervals on the stack. Whereas the second listing shows x being
stored 8 bytes into the stack, y 12 bytes further in, and z another 12
bytes further.

But as you can see from the immediate data in the instructions and the
use of the 32 bit registers that receive the data when fetched, only 4
bytes is being used for the data. So it appears that the second
program is wasting 4 bytes for the storage of x and 8 bytes each for y
and z.

Source code, generated offsets, machine code, and assembly language
generated by VS6.0:

1: void main(){
00401010 55 push ebp
00401011 8B EC mov ebp,esp
00401013 83 EC 4C sub esp,4Ch
00401016 53 push ebx
00401017 56 push esi
00401018 57 push edi
00401019 8D 7D B4 lea edi,[ebp-4Ch]
0040101C B9 13 00 00 00 mov ecx,13h
00401021 B8 CC CC CC CC mov eax,0CCCCCCCCh
00401026 F3 AB rep stos dword ptr [edi]
2: int x=2;
00401028 C7 45 FC 02 00 00 00 mov dword ptr [ebp-4],2
3: int y=5;
0040102F C7 45 F8 05 00 00 00 mov dword ptr [ebp-8],5
4: int z=0;
00401036 C7 45 F4 00 00 00 00 mov dword ptr [ebp-0Ch],0
5: z=x+y;
0040103D 8B 45 FC mov eax,dword ptr [ebp-4]
00401040 03 45 F8 add eax,dword ptr [ebp-8]
00401043 89 45 F4 mov dword ptr [ebp-0Ch],eax
6: }
00401046 5F pop edi
00401047 5E pop esi
00401048 5B pop ebx
00401049 8B E5 mov esp,ebp
0040104B 5D pop ebp
0040104C C3 ret

Source code, generated offsets, machine code, and assembly language
generated by VS2005:

1: void main(){

00411360 55 push ebp
00411361 8B EC mov ebp,esp
00411363 81 EC E4 00 00 00 sub esp,0E4h
00411369 53 push ebx
0041136A 56 push esi
0041136B 57 push edi
0041136C 8D BD 1C FF FF FF lea edi,[ebp+FFFFFF1Ch]
00411372 B9 39 00 00 00 mov ecx,39h
00411377 B8 CC CC CC CC mov eax,0CCCCCCCCh
0041137C F3 AB rep stos dword ptr es:[edi]
2: int x=2;
0041137E C7 45 F8 02 00 00 00 mov dword ptr [ebp-8],2
3: int y=5;
00411385 C7 45 EC 05 00 00 00 mov dword ptr [ebp-14h],5
4: int z=0;
0041138C C7 45 E0 00 00 00 00 mov dword ptr [ebp-20h],0
5: z=x+y;
00411393 8B 45 F8 mov eax,dword ptr [ebp-8]
00411396 03 45 EC add eax,dword ptr [ebp-14h]
00411399 89 45 E0 mov dword ptr [ebp-20h],eax
6: }
0041139C 33 C0 xor eax,eax
0041139E 5F pop edi
0041139F 5E pop esi
004113A0 5B pop ebx
004113A1 8B E5 mov esp,ebp
004113A3 5D pop ebp
004113A4 C3 ret

WTF???

BogusException
 
I

Ian Collins

BogusException said:
Why is it that VS 2005, VC++.NET needs 12 bytes to store an int, when
it can be done natively with 4? Mind you, even on 64-bit systems the
int is still supposed to be 4 bytes. An yes, the _pointer_ will be 8
bytes on a 64 bit system versus 4 bytes on a 32 bit one.
Your asking about an implementation issue, try a VS focused group.
 
K

Kai-Uwe Bux

BogusException said:
Why is it that VS 2005, VC++.NET needs 12 bytes to store an int, when
it can be done natively with 4?

You may want to ask that question in a forum where it is on-topic. Here, we
do standard C++ and VC++.NET specific questions are off-topic. Please refer
to the FAQ and to the weekly welcome message for details.
Mind you, even on 64-bit systems the
int is still supposed to be 4 bytes.

There is nothing in the standard that forbids 96bit ints on 64bit systems.
An yes, the _pointer_ will be 8 bytes on a 64 bit system versus 4 bytes on
a 32 bit one.

Pointers on such systems may or may not have 64 bits. The standard has
nothing to say about that.
So what gives?
???

Consider:

The two listings below came from compiling the following console
application with VS6.0 and VS2005 on a/the same 32 bit system:

1. void main(){

The standard says, main returns int. If the above compiles on your system,
it does so by means of an extension. The behavior of the program is then
undefined (as the standard does not impose any requirements on programs
that only compile by means of an extension). A diagnostic message is
required (i.e., your compiler is supposed to tell you that main returns
int). If you don't see that message, your compiler is not compliant (or you
run it with settings that make it non-compliant).
2. int x=2;
3. int y=5;
4. int z=0;
5. z=x+y;
6. }

Looking below, the first listing shows each int being stored at 4 byte
intervals on the stack. Whereas the second listing shows x being
stored 8 bytes into the stack, y 12 bytes further in, and z another 12
bytes further.

But as you can see from the immediate data in the instructions and the
use of the 32 bit registers that receive the data when fetched, only 4
bytes is being used for the data. So it appears that the second
program is wasting 4 bytes for the storage of x and 8 bytes each for y
and z.
[interesting piece of artwork snipped]

One can only guess what the compiler is thinking. Here are a few questions
the answers to which you might want to include into a post to a forum where
this is on-topic:

1) What happens to other types like signed char, signed long?
2) What happens to unsigned int?
3) Do the results depend on optimization settings?
4) Do the results depend on settings influencing run-time overflow checks?


Best of luck

Kai-Uwe Bux
 
B

BogusException

Ian,

Point taken. I'll also post to
microsoft.public.dotnet.languages.vc...

Feel free to offer any suggestions, though!

BogusException
 
I

Ian Collins

BogusException said:
Ian,

Point taken. I'll also post to
microsoft.public.dotnet.languages.vc...

Feel free to offer any suggestions, though!
Don't top-post on Usenet?
 
J

John Carson

BogusException said:
Why is it that VS 2005, VC++.NET needs 12 bytes to store an int, when
it can be done natively with 4?

Your claim is rather ambiguous. VC++ 2005 can produce both native and
managed code. If you are compiling your code as managed, then it is offtopic
here.

In any case, your claim is wrong. sizeof(int) is 4 with VC++ 2005, whether
managed or unmanaged.
Mind you, even on 64-bit systems the
int is still supposed to be 4 bytes. An yes, the _pointer_ will be 8
bytes on a 64 bit system versus 4 bytes on a 32 bit one.

So what gives?

Consider:

The two listings below came from compiling the following console
application with VS6.0 and VS2005 on a/the same 32 bit system:

1. void main(){
2. int x=2;
3. int y=5;
4. int z=0;
5. z=x+y;
6. }

Looking below, the first listing shows each int being stored at 4 byte
intervals on the stack. Whereas the second listing shows x being
stored 8 bytes into the stack, y 12 bytes further in, and z another 12
bytes further.

Starting addresses don't tell you storage requirements. The compiler can put
things where it pleases. Nothing says that sequentially declared variables
must be stored sequentially. Further, in Debug mode the compiler allocates
extra space for its debugging activities.

When I run the code in native Debug mode, z is stored *before* x and y. The
addresses are (using just the last two digits)

z 0x5C
x 0x60
y 0x64

(I get these by simply using cout << &x etc.). When I run the code in native
Release mode, I get:

x 0x70
y 0x74
z 0x78

When I compile the code as managed, I get a 4 byte gap in all cases.
 
R

Rolf Magnus

BogusException said:
Why is it that VS 2005, VC++.NET needs 12 bytes to store an int, when
it can be done natively with 4? Mind you, even on 64-bit systems the
int is still supposed to be 4 bytes.

Actually, on 64 bit systems, an int is "supposed" to be 64 bits, but isn't
required to. On most platforms, it isn't, because you'd run out of smaller
types.
An yes, the _pointer_ will be 8 bytes on a 64 bit system versus 4 bytes on
a 32 bit one.

If the implementation chooses this.
So what gives?

There is nothing in the standard that forbids that. Even if int only has 32
value bits, it's allowed to have as many padding bits as the implementation
deems necessary.
Consider:

The two listings below came from compiling the following console
application with VS6.0 and VS2005 on a/the same 32 bit system:

1. void main(){

From this point on, the program has undefined behavior. main() must return
int.
2. int x=2;
3. int y=5;
4. int z=0;
5. z=x+y;
6. }

Looking below, the first listing shows each int being stored at 4 byte
intervals on the stack. Whereas the second listing shows x being
stored 8 bytes into the stack, y 12 bytes further in, and z another 12
bytes further.

C++ doesn't require local variables to be stored on a stack. Further, it
doesn't say anything about how far they are away from each other. If you
really want to find out the size of int, just try:

#include <iostream>
int main()
{
std::cout << "An int is " << sizeof(int) << " bytes big\n";
}
 
R

robertwessel2

Why is it that VS 2005, VC++.NET needs 12 bytes to store an int, when
it can be done natively with 4? Mind you, even on 64-bit systems the
int is still supposed to be 4 bytes. An yes, the _pointer_ will be 8
bytes on a 64 bit system versus 4 bytes on a 32 bit one.

So what gives?


The exact code generated by a compiler is implementation dependent,
and OT here.

That being said, you're probably doing a debug build, and have both
runtime checks (-RTC1) and "edit and continue" debugging (-ZI) on,
which cause him to allocate extra space. Change either of those
options and he should stop.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top