I'm trying to learn about stack and heap at c++ and just started to print tests to learn how it's work.
I wrote this code:
`#include <iostream>
using namespace std;
int main (){
int a;
int b;
int *c;
int *c2;
int *d{new int};
cout << &a << " a= " << a << endl;
cout << &b << " b= " << b << endl;
cout << &c << " c= " << c << endl;
cout << &c2 << " c2= " << c2 << endl;
cout << &d << " d= " << d << endl;
delete d;
return 0;
}
the output is:
0x7ffefad88d00 a= 124
0x7ffefad88d04 b= 0
0x7ffefad88d08 c= 0
0x7ffefad88d10 c2= 0x400b20
0x7ffefad88d18 d= 0xec9c20
There are 3 things I do not understand:
why a value is 124?
why c value is 0 and not a pointer like c2 that have the same syntax?
why c size is just 2 byts and not 4?
a, b, c, d and the value of *d are uninitialized, reading them is undefined behavior. Anything can happen, nobody can predict the value of those variables. See this question for more information.
About the printout of the pointers, many implementations trim leading 0s. See this question. If I try to print out the values of pointers in Visual Studio 2015, I get the leading zeros.
why a value is 124?
a is uninitialized, hence reading it will give you unpredictable value. Reading uninitialized non-static local variable is UB. But, uninitialized global and static variables are initialized with 0 at compile time and reading them is fine.
why c value is 0 and not a pointer like c2 that have the same syntax?
c is also uninitialized, so what it points to is also undefined as mentioned above. It is a pointer like c2, but it points to NULL (which is 0).
why c size is just 2 bytes and not 4?
c size of a pointer is architecture and/or compiler dependent. In this case c occupied 8 bytes. subtract the address of c from the address of c2.
0x7ffefad88d10 - 0x7ffefad88d08 = 0x000000000008 these are hexadecimal values not decimal.
So, c is actually a pointer like c2 and occupies same space in the memory.
Related
#include <iostream>
using namespace std;
class V3 {
public:
double x, y, z;
V3(double a, double b, double c) {
x=a;
y=b;
z=c;
cout << "Addresses are " << &x << " " << &y << " " << &z << endl;
}
};
int main() {
V3 a(1,1,1), b(2,2,2), c(3,3,3), d(4,4,4);
cout << sizeof(a) << " " << sizeof(b) << " " << sizeof(c) << " " << sizeof(d) << endl;
}
In the code mentioned above, I'm trying to see how C++ stores objects in memory. On running this code, I get the following output -
Addresses are 0x7ffc5996b160 0x7ffc5996b168 0x7ffc5996b170
Addresses are 0x7ffc5996b180 0x7ffc5996b188 0x7ffc5996b190
Addresses are 0x7ffc5996b1a0 0x7ffc5996b1a8 0x7ffc5996b1b0
Addresses are 0x7ffc5996b1c0 0x7ffc5996b1c8 0x7ffc5996b1d0
24 24 24 24
So for object b, I wonder why I did not get 0x7ffc5996b178 as my address. Why is C++ skipping 8 bytes before starting the next object?
Converting a variety of comments into a Community Wiki answer.
Are the assignments necessary? Does anything change if you use V3(double a, double b, double c) : x(a), y(b), z(c) { cout << …; }? (I don't expect there to be a difference.) Did you try printing the addresses of the class objects in main()? Does that throw any light on things? Ultimately, though, your question is futile — the compiler is allowed to use any layout and alignment it chooses as long as it gives the correct results.
Just a guess: x86 cache lines are 64 bytes. By aligning this way, the first 2 objects would fit in 1 cache line, and the third would fit in a second cache line. If they were not aligned this way, the third object would be split across 2 cache lines which is bad. As already said though, it's not necessarily well-defined.
If compiled using clang on arch the objects are densely packed in memory, when using g++ they are not.
When I tried to access the value(which is an address) stored in the address pointed by the pointer variable, a garbage value is returned. I have posted the code and the output below.
Code:
#include<iostream>
using namespace std;
int main(){
int *a, b=10, *c;
a = &b;
c = &b+1;
cout << "Address of A : " << &a << endl;
cout << "Value of A : " << a << endl;
cout << "Value pointed by A : " << *a << endl;
cout << "Address of B : " << &b << endl;
cout << "Value of B : " << b << endl;
cout << "Value of C : " << c << endl;
cout << "Value pointed by C : " << *c << endl;
return 0;
}
Output:
Address of A : 0x7fff3e608d20
Value of A : 0x7fff3e608d1c
Value pointed by A : 10
Address of B : 0x7fff3e608d1c
Value of B : 10
Value of C : 0x7fff3e608d20
Value pointed by C : 1046514972
In the above program, the address pointed by c is the address of a yet *c gives garbage value 1046514972 instead of 0x7fff3e608d1c.
I know, I can access the value of A in some other way but my question is why couldn't I access it in this way. Is this an expected behaviour? If yes, can somebody please explain? Thank you.
c = &b+1;
//...
*c
That's undefined behaviour. Forming a pointer to the location after a variable is valid, but performing indirection through it is not1. Even though some object happens to be there, the compiler is free to do whatever it wants.
As to why 1046514972 is printed, that's 0x3e608d1c in hex. It's just the bytes of the 64 bit pointer reinterpreted as a 32 bit integer. You just happen to get something which kind of makes sense, but since this is undefined behaviour, it's semantically garbage.
1 Technically it's the l-to-rvalue conversion which is undefined, but you don't have to worry about that.
Why does the following code print 0? i.e. why does variable a is located right after variable d, even though pointer variable c is being declared between them?
#include<iostream>
using namespace std;
int main () {
unsigned int a = 100;
unsigned int &b = a;
unsigned int *c = &b;
unsigned int d = (unsigned int)(c);
int e = &d - c;
int &f = e;
e ++;
cout << e << " " << endl;
return 0;
}
Working backwards:
e ++;
cout << e << " " << endl;
If this prints 0, then the value of e before executing this code must have been -1.
int e = &d - c;
So the result of the above address subtraction must have been -1.
unsigned int a /* = whatever, the value of a doesn't matter */;
unsigned int &b = a;
unsigned int *c = &b;
unsigned int d /* = whatever, the value of d doesn't matter */;
b is a reference to a, so &b is equivalent to &a.
So &d - c is equivalent to &d - &a, and that subtraction yields -1.
Conclusion: the address of d is sizeof (unsigned int) bytes after the address of a. (Pointer subtraction is scaled by the size of the pointed-to type.)
Probably.
In fact, the behavior of subtracting pointers to two independently defined objects is undefined. The standard says literally nothing about what it should do.
In practice, a compiler will probably generate the simplest possible code for a pointer subtraction, and that simple code will probably treat unrelated pointers as if they were comparable, even though the language doesn't say they are.
It's likely, given your program's output, that b and d happen to be allocated next to each other. Nothing says that declared variables have to be allocated in the order in which you declare them. If you want objects to be allocated in memory in a define order, put them into a struct or make them elements of an array.
It's also likely that the same program will yield different results if you run it on a different system, or on the same system with a different compiler, or on the same system with the same compiler with different compiler options. In principle, it could even behave differently with everything the same but during a different phase of the moon.
And a compiler is permitted to assume that your code's behavior is well defined, and perform transformations that are valid only given that assumption. In effect, by subtracting two unrelated pointers, you have promised the compiler that they both point to elements of the same array object or just past the end of it (where a single object is treated as a 1-element array) (or that both are null pointers; that's one difference between C and C++). You have lied to the compiler, which means it is under no further obligation to you.
Don't do that.
Unless you explicitly place objects using your own memory management system, their relative positions in memory will be compiler- and system-dependent.
your line int e = &d - c; is substracting 2 unsigned int *.
In memory, &d is 8 bytes farther then c (it depend on your system, but we suppose that an int is 4 bytes). Effectively, you construct your stack in this way :
unsigned int a = 100; // &a is 0x0
unsigned int &b = a; // &b is 0x0 (it's just an alias)
unsigned int *c = &b; // &c is 0x4
unsigned int d = (unsigned int)(c); // &d is 0x8
An unsigned int use 4 bytes in memory.
So, when your are doing &d - c, it must return 2, because your are using pointer arithmetics with unsigned int* (4*2=8);
You can try with int e = (short*)&d - (short*)c result should be 4 because short size is 2 (2*4=8).
You can try with int e = (char*)&d - (char*)c result should be 8 because char size is 1 (1*8=8).
Try to print your variables and addresses to understand :
#include<iostream>
using namespace std;
int main () {
unsigned int a = 100;
unsigned int &b = a;
unsigned int *c = &b;
unsigned int d = (unsigned int)(c);
int e = (short*)&d - (short*)c;
//int &f = e;
//e ++;
cout << "&a: " << (unsigned int)&a << endl;
cout << "&b: " << (unsigned int)&b << endl;
cout << "&c: " << (unsigned int)&c << endl;
cout << "&d: " << (unsigned int)&d << endl;
cout << endl;
cout << " a: " << a << endl;
cout << " b: " << b << endl;
cout << " c: " << (unsigned int)c << endl;
cout << " d: " << d << endl;
cout << endl;
cout << " e: " << e << endl;
return 0;
}
Here, with int e = (short*)&d - (short*)c;, result is :
&a: 3220197356
&b: 3220197356
&c: 3220197360
&d: 3220197364
a: 100
b: 100
c: 3220197356
d: 3220197356
e: 4
Why after using strdup(value) (int)value returns you different output than before?
How to get the same output?
My short example went bad, please use the long one:
Here the full code for tests:
#include <stdio.h>
#include <iostream>
int main()
{
//The First Part
char *c = "ARD-642564";
char *ca = "ARD-642564";
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are equal
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
//The Second Part
c = strdup("ARD-642564");
ca = strdup("ARD-642564");
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are NOT equal Why?
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
int x;
std::cin >> x;
}
Because an array decays to a pointer in your case, you are printing a pointer (ie, on non-exotic computers, a memory address). There is no guarantee that a pointer fits in an int.
In the first part of your code, c and ca don't have to be equal. Your compiler performs a sort of memory optimization (see here for a full answer).
In the second part, strdup allocates dynamically a string twice, such that the returned pointers are not equal. The compiler does not optimize these calls because he does not seem to control the definition of strdup.
In both cases, c and ca may not be equal.
"The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1." source
So it's quite understandable that the pointers differ.
EDIT:
Though badly formatted this Question had a nice catch.So, I am editing this to retain this in a better format for future visitors who stumble across this question.
In the code sample below can someone please explain Why is the size of class different than expected after memcpy? What is the reason?
Here is the online demo on Ideone.
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
class A
{
public:
int a;
virtual void f1() { cout <<"inside a::f1\n"; }
A() { a = 1; }
};
class B
{
public:
int b;
virtual void f2() { cout <<"inside b::f2\n"; }
virtual void f5() { cout <<"inside b::f5\n"; }
B() { b = 2; }
};
class C : public A, public B
{
public:
int c;
void f1() { cout <<"inside c::f1\n"; }
void f2() { cout <<"inside c::f2\n"; }
virtual void f3() { cout <<"inside c::f3\n"; }
virtual void f4() { cout <<"inside c::f4\n"; }
C() { c = 3; }
};
int fun()
{
int a = 1;
return a * 2;
}
int main()
{
C c;
C c2;
int (*g)() = &fun;
void (A::*g1)() = &A::f1;
void (C::*g2)();
g2 = &C::f1;
(c.*g2)();
printf("%p\n",g2);
cout << sizeof(g2) << endl;
g2 = &C::f2;
(c.*g2)();
printf("%p\n", g2);
// Why is the output 1 here in g++ or visual C++?
cout << g2;
// Why is the sizeof returning 8? Please explain.
cout << sizeof(g2) << endl;
g2 = &C::f1;
std::vector<unsigned char> a_vec(sizeof(g2));
memcpy(&a_vec[0], &g2, sizeof(g2));
for(size_t i = 0; i < sizeof(g2); ++i)
{
cout << hex << static_cast<unsigned>(a_vec[i]) << " ";
}
cout << endl;
g2 = &C::f2;
std::vector<unsigned char> a_vec1(sizeof(g2));
memcpy(&a_vec1[0], &g2, sizeof(g2));
for(size_t i = 0; i < sizeof(g2); ++i)
{
cout << hex << static_cast<unsigned>(a_vec1[i]) << " ";
}
cout << endl;
cout << sizeof(g) <<endl;
cout << sizeof(g1) <<endl;
cout << sizeof(g2) <<endl;
// Why is sizeof(C) printing 14 and not 20 in visual C++?
// If yes why is this so ?
cout << sizeof(C) << endl;
cout << sizeof(c2) << endl;
cout << (&c) << endl;
cout << c.a << endl;
cout << c.b << endl;
cout << c.c << endl;
return 0;
}
From the above code sample the Output I get is:
inside c::f1
0x1
8
inside c::f2
0x5
18
1 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0
4
8
8
14
14
0xbffe375c
1
2
3
Following are my Questions:
Why is the output 1 here in g++ or visual C++?
cout << g2;
Why is the sizeof returning 8? Please explain.
cout << sizeof(g2) << endl;
Why is sizeof(C) printing 14 and not 20 in visual C++? If yes why is this so?
cout << sizeof(C) << endl;
Why is the sizeof returning 8. Please explain?
cout <<sizeof(g2)<<endl;
returns 8 because g2 is a pointer and size of an pointer on your enviornment is 8.
Why is the output 1 here in g++ or visual C++?
cout << g2;
The << operator does not have an overloaded version which accepts a pointer. So the pointer gets converted to a bool type, with a value 1, and cout prints it.
The C++ Standard allows this:
C++03 Standard 4.12 Boolean conversions
1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool.
Why is sizeof(C) printing 14 and not 20 in visual C++.
cout<<sizeof(C)<<endl;
It displays the size of C correctly just in hexadecimal(14 in hex == 20 in decimal). This is because you used the hex I/O manippulator to print an address before.
cout<<dec<<sizeof(C)<<endl;
will set the I/O manipulator to decimal mode again and it will output 20 as you expect.
A word about printf and type safety:
printf is not type safe.When using printf it is the users responsibility to pass the proper formart descriptor and data type to it. If there is a mismatch then an Undefined Behavior will occur. An Undefined behavior means that the program might crash or show any weird behavior.
printf( "%p\n", g2 );
Is an example of Undefined Behavior, there is a mismatch in the format descriptor and the data type. Note that the compiler does complain about this and you should always look out and check such warnings emitted by the compiler.
warning: format ‘%p’ expects type ‘void*’, but argument 2 has type ‘void (C::*)()’
The results of sizeof for a given type never change. (At least for a
conforming C++ program. g++, I believe, supports VLAs in C++, as an
extension, and the sizeof an object containing a VLA might change.)
With regards to your explicit questions:
printf( "%p\n", g2 );
is undefined behavior. You're passing a pointer to member to an output
formatter which requires a void*. (g++ will warn about this, I
believe, at least with certain options.) You might get just about
anything (including a program crash). Pointers to members are not
void*, and can't be converted to void*.
cout << g2;
I can't believe that this compiles.
cout << sizeof(g2) << endl;
sizeof(g2) returns 8 because this is the size of a pointer to member
on your system.
cout << sizeof(C) << endl;
Prints 14 because this is the size in hexadecimal of an object of type
C on your system. In other words, sizeof(C) is 20. Since you've
set output for hex, and never reset it, the output is hexadecimal.