Size of an object without using sizeof in C++ - c++

This was an interview question:
Say there is a class having only an int member. You do not know how many bytes the int will occupy. And you cannot view the class implementation (say it's an API). But you can create an object of it. How would you find the size needed for int without using sizeof.
He wouldn't accept using bitset, either.
Can you please suggest the most efficient way to find this out?

The following program demonstrates a valid technique to compute the size of an object.
#include <iostream>
struct Foo
{
int f;
};
int main()
{
// Create an object of the class.
Foo foo;
// Create a pointer to it.
Foo* p1 = &foo;
// Create another pointer, offset by 1 object from p1
// It is legal to compute (p1+1) but it is not legal
// to dereference (p1+1)
Foo* p2 = p1+1;
// Cast both pointers to char*.
char* cp1 = reinterpret_cast<char*>(p1);
char* cp2 = reinterpret_cast<char*>(p2);
// Compute the size of the object.
size_t size = (cp2-cp1);
std::cout << "Size of Foo: " << size << std::endl;
}

Using pointer algebra:
#include <iostream>
class A
{
int a;
};
int main() {
A a1;
A * n1 = &a1;
A * n2 = n1+1;
std::cout << int((char *)n2 - (char *)n1) << std::endl;
return 0;
}

Yet another alternative without using pointers. You can use it if in the next interview they also forbid pointers. Your comment "The interviewer was leading me to think on lines of overflow and underflow" might also be pointing at this method or similar.
#include <iostream>
int main() {
unsigned int x = 0, numOfBits = 0;
for(x--; x; x /= 2) numOfBits++;
std::cout << "number of bits in an int is: " << numOfBits;
return 0;
}
It gets the maximum value of an unsigned int (decrementing zero in unsigned mode) then subsequently divides by 2 until it reaches zero. To get the number of bytes, divide by CHAR_BIT.

Pointer arithmetic can be used without actually creating any objects:
class c {
int member;
};
c *ptr = 0;
++ptr;
int size = reinterpret_cast<int>(ptr);
Alternatively:
int size = reinterpret_cast<int>( static_cast<c*>(0) + 1 );

Related

How to get number of elements of string array via a pointer to a pointer

See Last line of code:
Trying to get number of elements from a array depending on a condition. How do i get the number of elements in an array when using an array like shown below:
using namespace std;
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
int main() {
const char **p;
if (true) {
p = options;
} else {
p = options2;
}
printf("%ld\n", sizeof(options)); // returns 24
printf("%ld\n", sizeof(options2)); // Returnns 16
printf("%ld\n", sizeof(options) / sizeof(p)); // returns 3
printf("%ld\n", sizeof(options2) / sizeof(p)); // returns 2
// How to use only pointer p to get the number of elements
printf("%ld\n", sizeof(p) / sizeof(p[0])); // returns 1 and not 3
return 0;
}
Sorry, but it is simply not possible to get an array's size from just a raw pointer to an array element.
One option is to store the array size in a separate variable alongside the array pointer, eg:
#include <iostream>
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
int main() {
const char **p;
size_t p_size;
if (some condition is true) {
p = options;
p_size = sizeof(options) / sizeof(options[0]); // or better: std::size(options) in C++17 and later
} else {
p = options2;
p_size = sizeof(options2) / sizeof(options2[0]); // or better: std::size(options2)
}
std::cout << sizeof(options) << "\n"; // returns 24
std::cout << sizeof(options2) << "\n"; // returns 16
std::cout << p_size << "\n"; // returns 3 or 2, based on condition
return 0;
}
In C++20 and later, you can use std::span instead (in C++14 and C++17, you can use gsl::span from the GSL library), eg:
#include <iostream>
#include <span>
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
int main() {
std::span<const char*> p;
if (some condition is true) {
p = options;
} else {
p = options2;
}
std::cout << sizeof(options) << "\n"; // returns 24
std::cout << sizeof(options2) << "\n"; // returns 16
std::cout << p.size() << "\n"; // returns 3 or 2, based on condition
return 0;
}
If you're going to write C++, write C++. You're starting from one of C's more questionable decisions, and then trying to force C++ to do the same thing. To twist Nike's phrase, "Just don't do it!"
std::array<char const *, 3> options {"Option1", "Option2", "Option3"};
std::array<char const *, 2> options2 {"Option1", "Option2"};
This makes it easy to retrieve the size of the array in question--and the size is part of the type, so all the work happens at compile time, so it imposes no runtime overhead. For example, if you do something like this:
template <class Array>
void showSize(Array const &a) {
std::cout << a.size() << "\n";
}
int main() {
showsize(options);
showSize(options2);
}
...what you'll find is that the compiler just generates code to write out the literal 3 or 2:
mov esi, 3 // or `mov esi, 2`, in the second case
call std::operator<<(std::ostream &, unsigned long)
[I've done a bit of editing to demangle the name there, but that's what the code works out to.]
Here's the un-edited version, in case you care.
If you really insist, you can side-step using an std::array as well:
const char *options[3] = {"Option1", "Option2", "Option3"};
const char *options2[2] = {"Option1", "Option2"};
template <class T, size_t N>
void showSize(T (&array)[N]) {
std::cout << N << '\n';
}
int main() {
showSize(options);
showSize(options2);
}
This doesn't actually use a pointer though--it passes the array by reference, which retains its type information, so the instantiated function template "just knows" the size of the array over which it was instantiated.
20 years ago, I'd have said this was a good way to do things. 10 years ago, I'd have preferred std::array, but realized it was new enough some compilers didn't include it yet. Nowadays, unless you really need to use an ancient (Pre-C++ 11) compiler, I'd use std::array.

Initialization of a vector inside a struct

struct geopoint {
double x;
double y;
const char * description;
};
struct georectangle {
double left_x;
double bottom_y;
double right_x;
double top_y;
const char * description;
};
struct geomap {
vector < geopoint * > geopointList;
vector < georectangle * > georectangleList;
};
struct geomap * geomap_new() {
struct geomap * newGeoMap = (struct geomap * ) malloc(sizeof(struct geomap));
return newGeoMap;
}
void geomap_delete(struct geomap * m) {
printf("%lu\n", m->geopointList.size());
for (int i = 0; i < m->geopointList.size(); i++) {
free(m->geopointList[i]);
}
printf("%lu\n", m->georectangleList.size());
for (int i = 0; i < m->georectangleList.size(); i++) {
free(m->georectangleList[i]);
}
free(m);
}
int main () {
struct geomap * m = geomap_new();
assert(m);
geomap_delete(m);
}
I'm new to C++ and I'm super confused about object initialization in this language... In Java you always use the new keyword when you initialize an object not of a primitive type. In C++, it looks to me that sometimes the default constructor is automatically executed and sometimes it isn't.
In the above snippet of code through the geomap_new() function I create an instance of struct geomap which contains two vectors of pointers.
My questions are the following:
How do I initialize these two vectors to be fresh new empty vectors? In Java I would use the new keyword... Is there such thing also in C++?
I'm asking this question because if I don't initialize them in any way, when I printf the size of these two vectors in the geomap_delete function, the size of the geopointList is 0, as it should be, but the size of the georectangleList is a big random number. It looks like to me that only the first vector is being initialized.
Another question...
If a start adding a lot of stuff in the vectors, these vectors will start growing up. Is it possible that their size will become bigger than the size of the struct itself? Is the struct going to realloc?
You could simplify your code to
#include <iostream>
#include <string>
#include <vector>
struct geopoint {
double x;
double y;
std::string description;
};
struct georectangle {
double left_x;
double bottom_y;
double right_x;
double top_y;
std::string description;
};
struct geomap {
std::vector<geopoint> geopointList;
std::vector<georectangle> georectangleList;
};
int main () {
geomap m;
std::cout << "m.geopointList.size(): " << m.geopointList.size() << '\n';
std::cout << "m.georectangleList.size(): " << m.georectangleList.size() << '\n';
m.geopointList.push_back({1, 2, "Description"});
m.georectangleList.push_back({1, 2, 3, 4, "Description"});
std::cout << "m.geopointList.size(): " << m.geopointList.size() << '\n';
std::cout << "m.georectangleList.size(): " << m.georectangleList.size() << '\n';
}
to avoid such problems. Avoid dynamic memory allocation and deallocation. Don't use malloc, free, new and delete.
"How do I initialize these two vectors to be fresh new empty vectors?" The default constructor does this for you.
"Is it possible that their size will become bigger than the size of the struct itself? Is the struct going to ```realloc``" The struct has a fixed size and contains two vectors. Both vectors contain a reference/pointer to dynamic memory outside of the struct. The struct and both vectors are created on the stack (in my example code) and the dynamic memory of the vectors is on the heap.

Changing the value of a int variable through pointers passed as arguments?

I want to modify values of some variables of a particular class by accessing address of these variables from another different class through a function. So, to access this address I try to pass pointers-to-variables as arguments to a function, where these pointers-to-variables will be set with the address of the variables. To learn how to do it, I'm trying to mimic in a simple program.
Here is my code:
#include <iostream>
using namespace std;
int numberA = 100;
int numberB = 200;
void referenceSetter(int *a, int *b)
{
*a = numberA;
*b = numberB;
}
void numberOutput()
{
cout << "A = " << numberA << endl;
cout << "B = " << numberB << endl;
}
int main() {
int *testA = 0;
int *testB = 0;
referenceSetter(testA, testB);
*testA = 30;
*testB = 40;
numberOutput();
return 0;
}
As you could see I declare numberA and numberB as global variables and set their values. The I try to get the address of these two variables through the function referenceSetter function and then after that I try to modify the values in those variables using the references. Apparently, I'm doing something wrong which leads to to have Unhandled Exception error exactly when I try to modify the values and try to set them as 30 and 40 resepectively.
Alternatively I tried the following approach:
#include <iostream>
using namespace std;
int numberA = 100;
int numberB = 200;
void referenceSetter(int *a, int *b)
{
a = &numberA;
b = &numberB;
}
void numberOutput()
{
cout << "A = " << numberA << endl;
cout << "B = " << numberB << endl;
}
int main() {
int *testA;
int *testB;
referenceSetter(testA, testB);
*testA = 30;
*testB = 40;
numberOutput();
return 0;
}
But this approach throws up the error uninitialized local variables testA and testB. Do I have to initialize pointers too?
Please help me find my mistake. Thanks.
The thing you're not understanding is that pointers are passed by value, just like any other variable. If you want the passed pointer to be changed, you need to pass a pointer to a pointer (or a reference to a pointer, but I'll leave that alone, as explaining references at this point will confuse you further).
Your main() is passing NULL pointers to referenceSetter(). The assignment *a = numberA copies the value of numberA (i.e. 100) into the memory pointed to by a. Since a is a NULL pointer, that has the effect of overwriting memory that doesn't exist as far as your program is concerned. The result of that is undefined behaviour which means - according to the standard - that anything is allowed to happen. With your implementation, that is triggering an unhandled exception, probably because your host operating system is detecting that your program is writing to memory that it is not permitted to write to.
If, after the call of referenceSetter() you want testA and testB to contain the addresses of numberA and numberB respectively, you need to change referenceSetter() to something like;
void referenceSetter(int **a, int **b)
{
*a = &numberA;
*b = &numberB;
}
This allows the values passed to be addresses of pointers. *a then becomes a reference to the pointer passed. &numberA compute the address of numberA, rather than accessing its value 100. Similarly for numberB.
The second change is to change main() so it calls the function correctly;
referenceSetter(&testA, &testB);
which passes the address of testA (and testB) to the function, so those pointers can be changed
You are trying to set the contents of address 0 to be equal to the other numbers, so when you're doing *a = numberA you're assigning a value of numberA to memory address 0.
Not sure, but I think what you're trying to achieve is this:
#include <iostream>
using namespace std;
int numberA = 100;
int numberB = 200;
void referenceSetter(int **a, int **b)
{
*a = &numberA;
*b = &numberB;
}
void numberOutput()
{
cout << "A = " << numberA << endl;
cout << "B = " << numberB << endl;
}
int main() {
int *testA = 0;
int *testB = 0;
referenceSetter(&testA, &testB);
*testA = 30;
*testB = 40;
numberOutput();
return 0;
}
This way, using pointers to pointers as arguments for referenceSetter(), you are actually modifying the address that your passed pointers are pointing to.
You are close, but the key is you need to pass the address of the value you want to set. You declare the values as int in main and pass the address by using the & operator:
int *testA = 0;
int *testB = 0;
referenceSetter(&testA, &testB);
*testA = 30;
*testB = 40;
numberOutput();
If you declare testA and testB as pointers in main and pass the pointer, the function gets a copy of the pointer instead of the address of the value you want to set.

Class accept and return array

I try to create a class that accept and return an array but I got some problem. I'm not sure if it is legal to return an array from a class. Or it could be done by returning an pointer to the array. Thank for any solution to the problem.
#include <iostream>
using namespace std;
class myclass {
private:
int Array[10];
public:
myclass (int temp[10]) {
for (int i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
int* returnArray2 () {
return this->Array; // hope it will return a pointer to the array
}
};
int main () {
int Array[10] = {1,2,3,4,5,6,7,8,9};
myclass A(Array);
cout << A.returnArray() << endl; // try to return an array and print it.
myclass* ptr = &A;
cout << *ptr->returnArray2 << endl; // error here
return 0;
}
First of all it is better to write the constructor either like
myclass ( const int ( &temp )[10] ) {
for (size_t i = 0; i < 10; i++) {
Array [i] = temp [i];
}
}
or like
myclass ( int temp[], size_t n ) : Array {} {
if ( n > 10 ) n = 10;
for (size_t i = 0; i < n; i++) {
Array [i] = temp [i];
}
}
Or even you may define the both constructors.
As for the returning value then you may not return an array. You may return either a reference to an array or a pointer to the entire array or a pointer to its first element
For example
int ( &returnArray () )[10] {
return Array;
}
In this case you can write in main
for ( int x : A.returnArray() ) std::cout << x << ' ';
std::cout << std::endl;
As for this statement
cout << *ptr->returnArray2 << endl; // error here
then you forgot to place parentheses after returnArray2. Write
cout << *ptr->returnArray2() << endl;
And the following member function is wrong because the expression in the return statement has type int * while the return type of the function is int
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
So either the function will coincide with the the second member function if you specify its return type like int *. Or you could change the return expression to *Array
int returnArray () {
return Array; // error here, I'm not sure if it is legal to return an array.
}
This is illegal because Array is not of int type. Your returnArray2 is valid, however. As for this line:
cout << *ptr->returnArray2 << endl; // error here
This is illegal because returnArray2 is a function; you must call it to return the int*:
cout << *ptr->returnArray2() << endl; // prints the first value in the array
Other notes:
Your capitalization is backwards; you should call your class MyClass and your member array arr or arr_, or you will confuse a lot of people.
return this->Array; this is redundant, you can simply return Array;
If you haven't heard of std::vector and std::array you should research those, as they are generally superior to C-style arrays.
In general, I would suggest to read a c++ book to get your basics correct as there are lot of issues in the code you posted.
Regarding your main question about exposing C style arrays in class public API, this is not a very robust mechanism. Do it if it is absolutely essential because of existing code but if possible prefer to use std::vector. You will mostly always end up with better code.
Other answers have corrected your coding errors, so i won't repeat that.
One other thing, your code suggests that the array size is fixed. You can pass and return the array by reference as well. Refer to: General rules of passing/returning reference of array (not pointer) to/from a function?

Random array value after return c++

My problem is I don't know what happens with data that I put into my arrays and how to make them stay in array. While debugging it is clear that arr gets initialized with zeros and arr2 with {1,2,3}. Functions however return some random values.. can someone help me to point out what it should be like?
#include <iostream>
#include <algorithm>
#include <vector>
class A
{
private:
double arr[5];
public:
A()
{
std::fill( arr, arr + 5, 0.0 );
};
~A() {};
void setArr( double arrx[] )
{
for ( int i = 0; i < 5; i++ )
arr[i] = arrx[i];
}
double* getArr(void) { return arr;}
};
int* probe()
{
int arr2[3] = {1,2,3};
return arr2;
}
int main()
{
A ob1;
double rr[5] = {1,2,3,4,5};
ob1.setArr(rr);
std::cout << ob1.getArr() << std::endl;
std::cout << probe() << std::endl;
system("Pause");
}
EDIT:
Now thanks to you i realize I have to loop the get** function to obtain all values. But how can I loop it if my planned usage is to write it like you see below into some file?
pF = fopen ("myfile.csv","a");
if (NULL != pF)
{
char outp[1000];
sprintf_s(outp, 1000, "%6d,\n", ob1.getArr());
fputs(outp, pF);
fclose(pF);
}
In
std::cout << ob1.getArr() << std::endl;
std::cout << probe() << std::endl;
You are actually printing the pointers (address), not the values which are double or int. You need to loop through all the elements of the array to print them.
As pointed out by P0W that accessing element of probe() has undefined behaviour, in that case you must make sure that the array should be valid. One quick solution is that declare the array static in the function.
As you want to write the value in the file
pF = fopen ("myfile.csv","a");
if (NULL != pF)
{
char outp[1000];
int i;
int retsofar=0;
for(i=0;i<5;++i)
retsofar+=sprintf_s(outp+retsofar, 1000-retsofar, "%6d,\n", ob1.getArr()[i]);
fputs(outp, pF);
fclose(pF);
}
you are trying to print the addresses of arrays returned by ob1.getArr() and probe() methods. Every time you are getting different addresses. If you want to print array, use loop.
In probe(), you are creating an array on stack and simply returning it's pointer. It is not safe. When it goes out of scope, its values can be overwritten and you may get un expected behaviour. So create that array on heap.