I tried to modify an object of A indirectly by allocating 8 bytes using std::allocator. I used <int> specifically, hoping it will return aligned memory for 2 integers. Then I modified an object of A.
Why do I only see A.x=9 in the bitset (towards the end 1001), what happened to A.y=10? Do I need to align the raw pointer returned by std::allocator?
I was expecting the output below:
0000000000000000000000000000100100000000000000000000000000001010
before=0000000000000000000000000000000000000000000000000000000000000000
---------------------
sizeof(A)=8
alignof(A)=4
x: 9 y: 10
---------------------
x: 9 y: 10
after=0000000000000000000000000000000000000000000000000000000000001001
#include <bitset>
#include <iostream>
struct A {
int x;
int y;
A() = delete;
friend std::ostream &operator<<(std::ostream &os, const A &a) {
os << "x: " << a.x << " y: " << a.y;
return os;
}
};
int main(int argc, char **argv) {
std::allocator<int> alloc;
auto raw = alloc.allocate(2);
std::bitset<64> before(*raw);
before.reset();
std::cout << "before=" << before << "\n";
std::cout << "---------------------\n";
std::cout << "sizeof(A)=" << sizeof(A) << "\n";
std::cout << "alignof(A)=" << alignof(A) << "\n";
auto a = reinterpret_cast<A *>(raw);
a->x = 9;
a->y = 10;
std::cout << *a << "\n";
std::cout << "---------------------\n";
std::bitset<64> after(*raw);
std::cout << *a << "\n";
std::cout << "after=" << after << "\n";
return 0;
}
I actually don't see any undefined behviour here.
The actual problem is that you seem to assume that before(*raw) creates a bitset with a snapshot of that memory region. But that is not what happens.
See: https://en.cppreference.com/w/cpp/utility/bitset/bitset
(you call the unsigned long long constructor)
If you simply write (before after):
unsigned long long raw_converted_to_long = *raw;
You see the value is 9 - this is the reason why the bitset is filled with 9.
i have a code:
#include <iostream>
using namespace std;
int main()
{
int *a, y = 6 , *yPtr = &y;
cout << "y:" << y << "| &y:" << &y << "| yptr:" << yPtr << "| *yptr:" << *yPtr << " | &yptr:" << &yPtr << " |a:" << a << endl;
*a = y;
cout<< "a:"<<a<<endl;
return 0;
}
when i assign *a to y *a = y then *a value not printed for me
This is because you never initialize a itself. *a points to who-knows-where, some random location. So you set some random location to 6.
As it's probably pointed outside of legal space, your program is probably quitting before it gets to the cout statement.
Here is my code:
#include <iostream>
using namespace std;
class MyClass{
int mem1;
float mem2;
};
class MyKids: public virtual MyClass{
int cmem1;
int cmem2;
};
class MyLawKids:public virtual MyClass{
int lmem1;
};
class MyGrands:public MyKids, public MyLawKids{
int gmem1;
};
int main(){
cout << "\n Size of MyClass: " << sizeof(MyClass) << " bytes" << endl ;
cout << " Size of MyKids: " << sizeof(MyKids) << " bytes" << endl ;
cout << " Size of MyLawKids: " << sizeof(MyLawKids) << " bytes" << endl ;
cout << " Size of MyGrands: " << sizeof(MyGrands) << " bytes" << endl ;
return 0;
}
Result:
Size of MyClass: 8 bytes
Size of MyKids: 20 bytes
Size of MyLawKids: 16 bytes
Size of MyGrands: 32 bytes
Process returned 0 (0x0) execution time : 0.094 s
Press any key to continue.
I think the size of MyGrands class its should be 36 bytes = (sizeof(MyKids + MyLawKids + int gmem1) - 4 bytes of virtual table pointer).
Why my result shown me "Size of MyGrands: 32 bytes" ?
MyGrands contains only one instance of MyClass due to MyKids and MyLawKids inheriting virtually from MyClass. Hence your calculation is wrong, by double counting the size of MyClass. By the way, in general you should not rely on a naive addition of the pieces being the same as the size of the whole. The compiler can add padding.
I'm just learning about function pointers in C++. The following examples do all compile and return the expected result, but I was taught that example 3 was the way to go. Why do the other examples still work?
There is another thing that seemed strange are the examples f,g,h,i which in contrast to the the examples above do not all work. Why don't they work, comparing to the examples 1-8?
int executeOperator1(int a, int b, int f(int,int)){
return f(a,b);
}
int executeOperator2(int a, int b, int f(int,int)){
return (*f)(a,b);
}
int executeOperator3(int a, int b, int (*f)(int,int)){
return f(a,b);
}
int executeOperator4(int a, int b, int (*f)(int,int)){
return (*f)(a,b);
}
int op(int x, int y){
return x+y;
}
int main(int argc, char *argv[])
{
int a = 2, b=3;
//the following 8 examples compile nicely:
cout << "a=" << a << " b=" << b << " res=" << executeOperator1(a,b,op) <<endl; //1
cout << "a=" << a << " b=" << b << " res=" << executeOperator2(a,b,op) <<endl; //2
cout << "a=" << a << " b=" << b << " res=" << executeOperator3(a,b,op) <<endl; //3
cout << "a=" << a << " b=" << b << " res=" << executeOperator4(a,b,op) <<endl; //4
cout << "a=" << a << " b=" << b << " res=" << executeOperator1(a,b,&op) <<endl; //5
cout << "a=" << a << " b=" << b << " res=" << executeOperator2(a,b,&op) <<endl; //6
cout << "a=" << a << " b=" << b << " res=" << executeOperator3(a,b,&op) <<endl; //7
cout << "a=" << a << " b=" << b << " res=" << executeOperator4(a,b,&op) <<endl; //8
//int f(int,int) = op; //does not compile
int (*g)(int,int) = op; //does compile
//int h(int,int) = &op; //does not compile
int (*i)(int,int) = &op;//does compile
return 0;
}
All your examples work because of wonderful so-called pointer decay rule. A function name decays to a pointer to function in almost all contexts. (Decay here means that original type information is lost, and all what is left is the pointer. Arrays do decay to pointers too in certain contexts).
So all your examples are semantically the same thing, and I would not call any of them preferred.
And just for the fun of it, this would compile too:
int executeOperator_insane(int a, int b, int f(int,int)){
return (***************f)(a,b);
}
Function, like arrays when passed as an argument to a function, decays into a pointer. For eg: A function taking two int parameters and returning an int would have a type of int (*) (int, int). But you can pass the function as reference as well, in which case you would have a type of int (&) (int, int).
To declare a value of type of above function pointer you would simply write :
typedef int (*FuncType) (int, int);
FuncType myFunc = op;
// OR
FuncType myFunc = &op;
The second way is usually preffered as it is more clear, but most of the compilers let the user do away with the first style.
Would recommend to go through below link:
http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_functions
When you use:
int f(int,int);
in main (or any place that is not an argument to a function), it declares f to be a function, not a pointer to a function. Hence, you cannot use
int f(int,int) = op;
On the other hand,
int (*g)(int,int) = op;
declares g to be a pointer to a function. Hence, it works.
When int f(int,int) is used as an argument to a function, it is equivalent to sing int (*f)(int, int).
See the below code:
#include <iostream>
using namespace std;
class temp
{
public:
int x; //8
char z; //4
int y;
};
int main()
{
temp tmp;
cout << "Total size=" << sizeof(tmp) << endl;
cout << "x=" << sizeof(tmp.x) /*<< "y" << sizeof(tmp.y) */<< "z=" << sizeof(tmp.z) << endl;
return 0;
}
Output comes:
Total size: 12
x=4 y=4 z=1
My question is: for different data types, stuffing / padding bytes will be placed. However how can we identify and calculate the total size of stuffing/padding bytes or how can we write code (generally not specific to this code) ?