I want to put both 1-dimensional array pointer and 2-dimensional array pointer in a union, so I can access data either way. In the following program I would like to see the value 9 is printed out by both ways.
#include <iostream>
class A {
public:
union {
int** array2D;
int* array1D;
};
A() {
array2D = new int*[1];
array2D[0] = new int[1];
}
};
int main() {
A a;
a.array2D[0][0] = 9;
cout << a.array2D[0][0] << endl;
cout << a.array1D[0] << endl;
cout << a.array2D << endl;
cout << a.array1D << endl;
}
The actual output:
9
146989080
0x8c2e008 //Pointer address of array2D
0x8c2e008 //Pointer address of array1D
The addresses are identical and by definition multidimensional arrays are stored in the same way as are one-dimensional arrays. I wonder why the two couts print out different results? What did I miss?
EDIT:
Thanks to the answers below, I can see what I missed.
The fix for accessing data from array1D is:
cout << *( (int*) a.array1D[0]) << endl;
First of all you are invoking undefined-behavior.
the standard says that you are only allowed to read from the member of a union that you last wrote t, reading array2D and array1D interchangeably is therefore not allowed (even though it often works in practice it is not recommended).
Second; using array1D you are trying to dereference and read the value at the address currently (supposedly because of UB) having been allocated for a new int*[1], the value of array2D[0][0] is located one further step down the path.
To access the value you are expecting from a.array1D you will need something as the below (not recommended)
**reinterpret_cast<int**> (a.array1D);
When you allocate multidimensional array using new, the way you do it, you are actually allocating a number of arrays.
The first one is an array of pointers to array. Thus your a.array1D[0] contains actually pointer to pointer to array, and you are printing a value of the pointer.
I am pretty sure if you will do the following:
cout << (int*)a.array1D[0] << endl;
you will get the same as:
cout << a.array2D[0] << endl;
When you print out the value of a.array2D is points to the beginning of the array. Since you are using a union both array1D and array2D occupy the same space and will contain the same value.
When you access the pointer value in a.array1D[0] you are telling it to get the first element of array1D. Because you are using a union this also points to the first element of array2D which happens to be a pointer.
Related
I've been stuck on this problem and I'm hoping someone can explain where I'm wrong on this. I'm working on an assignment where I need to:
1) Allocate an array that can contain 100 int values by calling allocIntArray and assign the returned pointer to ptr1.
2) Use the new operator to allocate an array of integers using the parameter as the size of the array.
3) Return the pointer that is returned by the new operator.
4) Print out the new array.
I'm trying to print out the array after passing the size I want through the function.
int main() {
int *ptr = NULL;
ptr1 = *allocIntArray(100);
cout << ptr1 << endl;
return 0;
}
//The function I want to call
int *allocIntArray(int size) {
int *newarr = nullptr;
newarr = new int[size];
return newarr;
}
However when I call the function, the output comes out as 00F011E8.
I'm currently trying to understand why this is the output and not the first value in the array. (Just the number 1)
I've been having a lot of trouble grasping pointers any help understanding would be greatly appreciated.
Thanks to everyone who took the time to respond.
From what I understand from assignment directions, I shouldn't need to use vectors. I'm trying to modify my current code to display the array output and this is what currently comes up when I run it.[enter image description hereMy current results
At first, if you're using C++, you should use std::vector/std::array. This avoids a huge amount of possible problems.
It would look like:
#include <iostream>
#include <vector>
int main()
{
// create array of size 10 and initialize it with 0's
std::vector<int> vec(10, 0);
// print array
for(auto a : vec)
std::cout << a << '\t';
std::cout << std::endl;
}
If it's some kind of exercise, you have done four big mistakes:
you dereference the returned pointer to the array. So you get the value of the first element in the array and not the array itself. Simply remove the *.
you print out the address of the first element of the array. To print the array, you have to iterate over each element of the array. This can be done in a for loop:
for(int i = 0; i < 10; ++i)
std::cout << ptr1[i] << '\t';
you want to print out the array uninitialized. In fact, you try to print out some random values which are there in the memory. At first, you have to assign the elements values.
you forget to delete the array by using
delete[] ptr1;
I just have to answer as you seem to be missing some important fundamentals. Either the instructor should be dismissed or you have not paid enough attention in the class. So...
ptr1 = *allocIntArray(100);
You could not have pasted code that compiles, ptr1 is not declared.
You need to understand what the * operator does. What ever value to the right of * must be a pointer. What a pointer is should be fundamental in your understanding. If you had:
int* ptr1 = *allocIntArray(100);
You should have gotten a compiler error, so you must have:
int ptr1;
Somewhere along the line. As allocIntArray(...) returns a pointer, then *allocIntArray(...) gives you an integer.
You would have wanted to:
int* ptr1 = allocIntArray(100);
To get a pointer to the new array. Then you:
std::cout << ptr1 << std::endl;
So, what is ptr1? If it is a pointer then all you are doing is printing the pointer value. Per your stated problem, I'd say ptr1 is in fact a pointer. std::cout has not facility to work with a pointer as you expect. At that, it would have no way of determining the size of your array.
You would want to (And it hurts my fingers to write like this):
for(size_t i= 0; i < 100; ++i)
std::cout << ptr1[i] <<" ";
But!!!
4) Print out the new array.
So what will it print? There was never an instruction to initialize the array. It will print out what ever garbage is sitting in the array when it was created.
Side note, that the instructor has you doing a:
using namespace std;
Says much, as he/she should never have allowed it.
Hello i'm a noob in programming, i have a small doubt regarding pointers
#include<iostream>
using namespace std;
int main()
{
int myAge = 16;
int* agePtr = &myAge;
cout << "address of pointer" << agePtr << "Data at memory address" << *agePtr << endl;
int badNums[5] = {4, 13, 14, 24, 34};
int* numArrayPtr = badNums;
cout<< "address" << numArrayPtr << "value" << *numArrayPtr << endl;
numArrayPtr++;
cout<< "address" << numArrayPtr << "value" << *numArrayPtr << endl;
return 0;
}
In the first case while pointing an integer i use &myAge where as in
the second case of incrementing Arrays if i use &badNums the compiler
is returning an error, but if i use badNums its compiling why should
we use badNums instead of &badNums in the second case?
how can I increment the value in integer using pointers?
Arrays implicitly decay to pointers, as per the rules of c++. There are many implicit conversions in c++, this is one of them. When assigning an array to a pointer, it provides you with a pointer to the first element in the array.
Taking the address of an array (&badNums) will yield a pointer to the array, not to the first element. Array pointers are slightly more complicated and encode the size of the array in the type. The correct type for that assignment would be int (*numArrayPtr)[5] = &badNums; where numArrayPtr is a pointer to an array of 5 ints.
To increment a value pointer to by a pointer, you must first dereference that pointer using operator * just like if you wanted to read from or write to that value. It would look like (*numArrayPtr)++;.
In the first case, using &myAge refers to the address of that integer value. The reason why you must use badNums instead of &badNums when doing assignment to the integer pointer is because badNums is already an integer pointer. Arrays implicitly decay into pointers, so using &badNums in that assignment would work if you were doing:
int **numArrayPtr = &badNums;
which is just a pointer to a pointer to the address of badNums. So,
int *numArrayPtr = badNums;
just means that we have a pointer to the address of badNums.
When we have an integer pointer like this, you can increment the value of each integer in the array by doing this:
for (int i = 0; i < 5; i++){
numArrayPtr[i]++;
}
or, we can do the same thing without using array notation:
for (int *i = numArrPtr; i != numArrPtr + 5; i++){
(*numArrPtr)++;
}
I hope that answers your questions fully.
I have a small doubt regarding pointers
Just like i in badnums[i] is an index within array badnums[], a pointer is an index to something stored in memory. Since any variable is stored in memory, you can access the contents of a variable with a pointer to whatever it contains (which is what languages implicitly do when using variables in your code).
The difference is that with pointers you must know the type of what the pointer designates, while an index uses the known type of the indexed elements of the variable it points to... because sooner than later you will iterate the contents of some known variable using a pointer.
I have created objects by using new, but then have dereferenced them before adding them to a vector. Despite trawling the internet I cannot work out how I can call delete on these items. I want to do this just using standard C++ and STL I don't want (e.g.) to use Boost libraries.
As you can see a, b and c lose scope and I am left with what I presume to be copies in the vector. How can I go about deleting these. I don't want to store pointers in the array as I will need to pass an API function an array of doubles.
Please someone - how do I delete these objects?
#include <iostream>
#include <vector>
using namespace std;
vector<double> vectorDouble;
void createObjects();
void createObjects() {
double* a=new double(13);
double* b=new double(14);
double* c=new double(15);
//a,b and c are not contiguous memory blocks
cout << "memory location of a: " << a << endl;
cout << "memory location of b: " << b << endl;
cout << "memory location of c: " << c << endl;
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
}
int main() {
createObjects();
//the memory addresses are contiguous 8 byte chunks
cout << "vector memory at 0: " << &(vectorDouble[0]) << endl;
cout << "vector memory at 1: " << &(vectorDouble[1]) << endl;
cout << "vector memory at 2: " << &(vectorDouble[2]) << endl;
//get pointer to the 2nd element
double *P=&(vectorDouble[1]);
//dereference and look inside - two memory locations both contain the value 14
cout << "vector Pointer P ["<< P <<"] contains " << *P <<endl;
//Which should I call delete on? I have lost reference to the original pointers.
//How should I call delete on the vector?
cout << "deleting pointer that references 2nd vector element" << endl;
delete P; //********* CRASH **********
cout << "Done deleting" << endl;
}
The objects you need to delete are not in the vector, because your vector elements are not created with new. You are just passing the copy of the malloc'd doubles, not the actual allocated double to the vector, when you use the dereference operator in the push_back.
You are actually just leaking them - your code would run fine without allocating doubles:
void createObjects() {
vectorDouble.push_back(13);
vectorDouble.push_back(14);
vectorDouble.push_back(15);
}
As everyone points out, there is no reason whatsoever to invoke new in your program:
void createObjects() {
vectorDouble.push_back(13);
vectorDouble.push_back(14);
vectorDouble.push_back(15);
}
Suppose, however, that you do have some reason to call new. (I can't imagine what it might be, but let's assume you are a genius). Here is how you would do that:
void createObjects() {
double* a=new double(13);
double* b=new double(14);
double* c=new double(15);
//a,b and c are not contiguous memory blocks
cout << "memory location of a: " << a << endl;
cout << "memory location of b: " << b << endl;
cout << "memory location of c: " << c << endl;
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
delete a;
delete b;
delete c;
}
You see, the push_back doesn't put a copy of your pointer in the vector, it puts a copy of your object in the vector. Once you've made the copy of your object, then your object's memory serves no continuing purpose, and can be destroyed.
The function createObjects is not putting the allocated values into the vector; it is putting in the values and then leaking the memory that a, b, and c pointed to. The call:
vectorDouble.push_back(*a);
stores the value pointed to by a in the vector (*a dereferences the pointer, which you probably already know). Once that function returns, the pointers are lost. You cannot retrieve them from the vector. You would either need to make a vector of pointers to doubles or (more likely) don't even allocate values; just store the doubles.
I think I've got the problem, on:
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
You are passing a, b and c as values so the array don't really contains the variables you have created (that's why they now have different memory address, they are a copy of the content of your variables!). Then you can delete the variables inside the method, don't use pointers inside the method or use an double* vector.
Your leak is in createObjects(), because std::vector<>::push_back() makes a copy of its argument. You should delete the pointer before the end of scope of createObjects().
That said, I don't see why you use dynamic allocation to begin with. If you can avoid that please do (and you can, with a smart pointer like std::unique_ptr<>, or better yet with plain old doubles).
The basic pseudo code looks like this:
void myFunction()
{
int size = 10;
int * MyArray;
MyArray = new int[size];
cout << size << endl;
cout << sizeof(MyArray) << endl;
}
The first cout returns 10, as expected, while the second cout returns 4.
Anyone have an explanation?
MyArray is only a pointer, which on your system, has a size of four bytes.
When you dynamically create an array, you need to keep track of the size yourself.
If you created an automatic array or static array,
int MyArray[10];
then sizeof(MyArray) would be 40. As soon as the array decays to a pointer, though, e.g. when you pass it to a function, the size information is lost.
Related to a recent question.
A pointer is a pointer, regardless of what it points at. You have to keep track of the size yourself. Better is to use a std::vector.
sizeof returns the size of an expression, which in this case is the size of the type int*. This always has the same size, regardless of its value.
For comparison, consider:
int i = 0;
i = 23434634;
No matter what value i takes on, the size of i itself is still only sizeof(i) == sizeof(int). A pointer is the same, it just holds a different kind of value.
MyArray is of type int*. sizeof() when called on a variable returns the size of the type of that variable.
While there is a special case for arrays, it's only for stack arrays (i.e. int MyArray[3];).
MyArray is an int*, and sizeof(int*) on your system is 4.
MyArray is not an array. It is a pointer that happens to point to a block of memory in which you allocated an array.
int MyArray[10];
cout << sizeof(MyArray) << endl;
That should print 40, which is how big 10 ints happens to be on your system. In this case, MyArray is an array. So the size of the type includes the size of all the elements of the array.
MyArray in this second case will decay into a pointer, but they are still two distinct types.
#include <iostream>
#define P(expr) std::cout << #expr << " = " << (expr) << std::endl
namespace {
void myFunction(size_t size) {
int *pointer = new int[size];
int MyArray[size];
P(size);
P(sizeof(MyArray));
P(sizeof(pointer));
delete [] pointer;
}
}
int main() {
myFunction(10);
}
Output:
size = 10
sizeof(MyArray) = 40
sizeof(pointer) = 8
I'm trying to simply print out the values contained in an array.
I have an array of strings called 'result'. I don't know exactly how big it is because it was automatically generated.
From what I've read, you can determine the size of an array by doing this:
sizeof(result)/sizeof(result[0])
Is this correct? Because for my program, sizeof(result) = 16 and sizeof(result[0]) = 16 so that code would tell me that my array is of size 1.
However that doesn't appear correct, because if I manually print out the array values like this:
std::cout << result[0] << "\n";
std::cout << result[1] << "\n";
std::cout << result[2] << "\n";
std::cout << result[3] << "\n";
etc...
...then I see the resulting values I'm looking for. The array is upwards of 100+ values in length/size.
It seems like it should be very simple to determine the size/length of an array... so hopefully I'm just missing something here.
I'm a bit of a C++ newb so any help would be appreciated.
You cannot determine the size of an array dynamically in C++. You must pass the size around as a parameter.
As a side note, using a Standard Library container (e.g., vector) allieviates this.
In your sizeof example, sizeof(result) is asking for the size of a pointer (to presumably a std::string). This is because the actual array type "decays" to a pointer-to-element type when passed to a function (even if the function is declared to take an array type). The sizeof(result[0]) returns the size of the first element in your array, which coincidentally is also 16 bytes. It appears that pointers are 16 bytes (128-bit) on your platform.
Remember that sizeof is always evaluated at compile-time in C++, never at run-time.
As a side comment, there are better ways of checking the size of an array (for the cases where the array is in scope and has not decayed into a pointer) that are typesafe:
// simple: runtime result
template <typename T, std::size_t N>
inline std::size_t sizeof_array( T (&)[N] ) {
return N;
}
// complex: compile time constant
template <typename T, std::size_t N>
char (&static_sizeof_array( T(&)[N] ))[N]; // declared, not defined
#defined SIZEOF_ARRAY( x ) sizeof(static_sizeof_array(x))
In both cases the compiler will detect if you try to pass in a pointer (dynamic array or decayed array):
void f( int array[] ) { // really: void f( int *array )
{
// sizeof_array(array); // compile time error
// int another[SIZEOF_ARRAY(array)]; // compile time error
}
int main() {
int array[] = { 1, 2, 3 };
std::cout << sizeof_array(array) << std::endl; // prints 3
int another_array[ SIZEOF_ARRAY(array) ];
std::cout << sizeof_array(another_array) << std::endl; // 3 again
}
If what you have is a "real" array, then the sizeof(x)/sizeof(x[0]) trick works. If, however, what you have is really a pointer (e.g. something returned from a function) then that trick doesn't work -- you'll end up dividing the size of a pointer by the sizeof a pointer. They are pointers to different types, but on a typical system all pointers are the same size, so you'll get one. Even when the pointers are different sizes, the result still won't have anything to do with how many strings you have.
Better use std::vector<std::string> instead of a raw array. Then you don't have to manually manage the arrays memory and you can use the size() method if you want to know the number of elements.
If you use a dynamically allocated raw array you are expected to keep track of its size yourself, the size cannot be obtained from the array. Best save it in an extra variable.
The sizeof(array)/sizeof(element) works for fixed-length-array of fixed-length-arrays (not of pointers).
As an array of strings we most often use a (fixed-length-)array of pointers-to-various-(fixed-)length-strings so this trick wouldn't work.
sizeof() is used for objects which size is known at compile time. It's not applicable to dynamically allocated data itself.
When an object contains pointers like in the case of an array of strings,
sizeof() returns the size of the highest-level (fixed-size) structure. Often it's just the size of a single pointer. It does not include the size of the allocated data pointed to by the pointers. Because that data actually is not part of the main object, it's indeed one or more separate objects (we have aggregation here instead of composition, see http://en.wikipedia.org/wiki/Object_composition).
In C++ using vectors is very convenient for your needs. Other suitable standard containers could be used too.
length() and size() methods are synonyms, see http://www.cplusplus.com/reference/string/string/size/)
P.S. Please note that for std::string s object sizeof(s) is a constant independent of the actual (variable) string length returned by s.length(). The actual allocated memory size is returned by s.capacity() and could be greater than length().
Example using vector array:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s = "01234";
cout << "s[" << s.length() << "]=\"" << s << "\"" << endl;
cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
cout << endl;
s += "56789012345";
cout << "s[" << s.length() << "]=\"" << s << "\"" << endl;
cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
cout << endl;
vector<string>vs={"12","23","345","456","567","67888","7899999999","8","9876543210"};
cout << "vs[" << vs.size() << "]={";
size_t sz=0;
for (size_t index=0; index<vs.size(); index++)
{
sz+=vs[index].size();
if (index>0)
cout << ",";
cout << "\"" << vs[index] << "\":" << vs[index].size();
}
cout << "}:" << sz << endl;
cout << "sizeof(vs)=" << sizeof(vs) << " (implementation dependent)" << endl;
return 0;
}
Result:
s[5]="01234"
sizeof(s)=8 (implementation dependent)
s[16]="0123456789012345"
sizeof(s)=8 (implementation dependent)
vs[9]={"12":2,"23":2,"345":3,"456":3,"567":3,"67888":5,"7899999999":10,"8":1,"9876543210":10}:39
sizeof(vs)=24 (implementation dependent)
template< class T, size_t N >
std::size_t Length(const T(&)[N])
{
return N;
};
std::cout << Length(another_array) << std::endl;
In String vector use size() method
Something to be aware of: text can be represented in different methods. An array of text can also be represented in different methods.
Array of pointers to C-Style strings
A common method is to have an array of pointers to char. The issue is that the size of the array doesn't represent the size of all of the text. Also, the ownership of the data or pointer must also be established, as the text may have to be delete (and can the callee delete the text or does the caller?). Because it is an array, the size of the array must always accompany the array in all parameters (unless the array is always a fixed size).
Array of char - packed text
Another method is to pass an array of char and have the strings contiguous in the array. One string follows the termination char of the previous. With this array, the total size of all of the strings is represented, no wasted space. Again, with arrays, the size of the array must accompany the array when passed around.
Array of std::string
In C++, text can be represented using std::string. In this case, the array represents the quantity of strings (similar to the array of C-Strings above). To get the total size of all the strings, one must sum up the size of each individual string. Since this is an array, the size of the array must be passed also.
Summary
During run-time array sizes must accompany the array when the array is passed around. sizeof is only processed at compile time. A simpler structure is std::vector, which handles size and memory allocation dynamically.