I have passed pointer to a pointer as a parameter to function and the goal is to make an array inside of that function. I have done that step properly and also inside of the function checked the *address and value of the array(local) as well as pointed by the pointer(op_ptr_array_) and they are the same(as desired).
But the problem is occurring while I want to dereference the provided pointer(op_ptr_array). The values are wrong while addresses are matched with the pointed array(local).
My idea is that as the address of op_ptr_array(pointer passed to the function) is equal to the local and op_ptr_array_ (array and pointer inside of the function) so using a for loop *(op_ptr_array+i) will provide me the result where i < op_size.
The approach I have taken is as follows:
#include <iostream>
void op_calculation(unsigned int* ip_ptr_array_,
unsigned int ip_size_,
unsigned int** op_ptr_array_,
unsigned int* op_size_)
{
*(op_size_) = ip_size_ + 2;
std::cout<<"op_size_ address: "<<op_size_<<std::endl;
std::cout<<"op_size_ value: "<<*(op_size_)<<std::endl;
unsigned int local[*(op_size_)];
std::cout<<"making local array to be pointed by op_ptr_array_\n";
for (unsigned int i = 0; i< *(op_size_); i++)
{
local[i]=i+1*3;
std::cout<<local[i]<<" ";
}
std::cout<<"\n";
*op_ptr_array_ = &local[0];
local[3] = 87; // for checking pointer charecter
for (unsigned int i = 0; i < *(op_size_); i++)
std::cout<<"array address: "<<&local[i]<<" ,op_ptr_array address: "<<(*op_ptr_array_)+i<<" ,val of array: "<<local[i]<<" ,val at op_ptr_array: "<<*((*op_ptr_array_)+i)<<std::endl;
// here value and addresses are same which is desired
}
int main()
{
unsigned int ip_size = 10;
unsigned int* ip_ptr_array = new unsigned int[ip_size];
unsigned int op_size;
unsigned int* op_ptr_array;
for(unsigned int i = 0; i < ip_size; i++)
{
ip_ptr_array[i] = i+2*2;
}
op_calculation(ip_ptr_array,
ip_size,
&op_ptr_array,
&op_size);
std::cout<<"Value printing after operation of op_calculation function\n";
std::cout<<"op_size: "<<op_size<<std::endl;
std::cout<<"op_ptr_array\n";
for(unsigned int i = 0; i < op_size; i++)
std::cout<<"Address: "<<(op_ptr_array+i)<<" , Value: "<<*(op_ptr_array+i)<<"\n";
/* Here only addresses are same with `local array` and
address pointed by op_ptr_array_ pointer` which you will find in op_calculation
function but values are different*/
std::cout<<"\n";
return 0;
}
Any idea where I am making the mess is highly appreciable.
Variable local is being declared as a local variable (i.e. on the stack). This falls out of scope when the function op_calculation exits, which means that the memory originally used to allocate local may be used for something else.
This can be corrected by converting local to a pointer and using new to allocate memory for the array’s contents or by declaring local as static, which will place the contents elsewhere in RAM. Keep in mind, if you use static any future calls to op_calculation will overwrite the contents of the array, even if it is still in use elsewhere. This would not be a problem if you used new, but if you use new you will need to remember to deallocate the array using delete[] when it is no longer needed.
Related
If i want to give a value to int *num2, how would i do this ?
#include <stdio.h>
int main(int argc, const char * argv[]) {
// insert code here...
struct az {
int num1;
int *num2;
};
struct az test;
test.num1 =20;
printf("\n %d",test.num1);
return 0;
}
int *num2; is a pointer to some place in the memory that contains an int value. Since you just declare a pointer without any memory allocating, it is simply points to nothing (or random place).
You have to allocate memory then assign a value to this memory:
test.num2 =new int(20);
However, do not forget to delete this allocated memory when you finish:
delete test.num2;
The real question here, do you really want that pointer here? probably not.
You can assign num2 in the same way as num1. Of course, since it's not an int but an int*, you can't assign 20 to it - you can assign the address of some int variable instead:
struct az {
int num1;
int *num2;
};
struct az test;
test.num1 = 20;
int i;
test.num2 = &i;
To assign a value to the integer that test.num2 points to, you must de-reference the pointer with an asterisk, like so:
test.num2 = new int(20); // Allocates memory and sets the pointer to this memory
*(test.num2) = 10; // Assign a value of 10 to the int that test.num2 points to
To assign an address to the pointer, you must either assign another pointer to it, or assign it's value by referencing an int with an ampersand:
test.num2 = new int(20); // Allocates memory and sets the pointer to this location
int *ptr = new int(10);
delete test.num2; // Free memory that test.num2 pointed to
test.num2 = ptr // Makes test.num2 point to the same int as ptr
int x = 10;
test.num2 = &x; // Makes test.num2 point to x
In your example num2 is typically used as a pointer to a dynamically allocated array. However, neither num2 nor num1 is a good name in this case. Let's instead declare our dynamic array type as a record with the fields length and items:
struct Array {
int length;
int *items;
};
typedef struct Array Array;
If we have a variable a of type Array, before we can assign values to its elements we must first allocate memory for the array. In C this is typically done with the function malloc. This function, however, is rather error prone to use so it's a good idea to define a macro function which simplifies memory allocation:
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof (ptr)[0])
After having called NEW_ARRAY we can assign values to the array:
int length;
Array a;
length = 20;
a.length = length;
NEW_ARRAY(a.items, length);
a.items[0] = 37;
a.items[1] = 19;
...
When we are done with the array we can release the memory used by the elements:
free(a.items);
I am learning classes in c++ so I try different things to get used to the classes. Here I am trying to pass a pointer to a class function:
class Pointerss{
int size;
public:
Pointerss(int);
void f();
int *a;
};
Pointerss::Pointerss(int siz){
size = siz;
}
void Pointerss::f(){
cout<<"Size is:"<<size<<"\n";
for (int i=0; i<size; ++i) {
cout<<"a is:"<<a[i]<<"\n";
}
}
int main() {
int size = 5;
Pointerss dd (size);
Pointerss * p = new Pointerss(size);
p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
p->a;
dd.f();
return 0;
}
So the "size" is initialized by a constructor and when "f()" is called the correct digit is printed. But when I assign "p" to "a" ("p->a") and then call "f()" some random numbers are printed. My computer prints :
Size is:5
a is:0
a is:0
a is:1
a is:0
a is:1606416856
Program ended with exit code: 0
what is the difference between "a" and "size" and what should I do to pass a pointer to a function?
Random numbers are printed because Pointerss::f dereferences dd.a which you never initialized. Dereferencing an uninitialized pointer results in undefined behaviour.
That's not the only bug you have. You also allocate memory for a single Pointerss object, which is pointed by p, but then proceed to construct objects in p[1..4] which point to unallocated memory. That also results in undefined behaviour.
Thirdly, you never deallocate the memory that you allocated with new.
Step 1 would be to understand pointers. When you make a int* you only reserve memory to store the pointer itself. You don't reserve memory for any int. So when you try to print the integers you just get random numbers (or perhaps a program crash).
So your class can't hold any integers. You need to change it so that you reserve memory in the constructor and release it in the destructor.
class Pointerss{
int size;
public:
Pointerss(int);
~Pointerss();
void f();
int *a;
};
Pointerss::Pointerss(int siz){
size = siz;
a = new int[size]; // Reserve memory for size integers
// Do some initialization if needed, e.g.
for (int i=0; i < size; i++) a[i] = i;
}
Pointerss::~Pointerss(){
delete[] a; // Release the memory again
}
void Pointerss::f(){
cout<<"Size is:"<<size<<"\n";
for (int i=0; i<size; ++i) {
cout<<"a is:"<<a[i]<<"\n";
}
}
Further you can't make a single pointer to an instance of the class, i.e.
Pointerss * p = new Pointerss(size);
and then use it like
p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
because that is operating on 5 different instances.
Finally the code:
p->a;
does nothing!
You could do
p->a[0] = 5;
but it is unclear what you are trying to do.
Notice that dd and p are refering to two different instances of your class so changing something inside *p doesn't change dd at all.
If you had done:
Pointerss *p = ⅆ
then *p and dd would be the same instance.
To fully understand how pointers, values, and references work, I am making a basic C++ program that attempts to tamper with some static and dynamic arrays and understand exactly how they should be passed in.
First I generate a static array of 3 elements. I then pass it into a function that modifies all elements. I then pass it into another function with a slightly different signature, but can also alter the array's values.
Next I generate a dynamically sized array, pass it into a function by reference so that all of the values in this dynamically sized array can be altered.
The code is as follows:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
All of the above code works how I want it to, I just have a few questions as to why (some of the methods of passing arrays by reference I have found on other SO questions).
In the changeIndexStaticArrayMethod1() and changeIndexDynamicArrayMethod1() functions, why are we able to use the dereference * operator for our array as reference? My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator. I know that with arrays, it is much different than using variables, but also, why will the following not work for single int variables:
void changeStaticNumber(int* num){
num = 100;
}
Obviously the above will work if we use &num and not int* num, and obviously I don't fully understand the relationship between pointers and arrays, but I cannot figure out why when we pass an array by reference, int* staticArray is ok.
Any explanation for these problems I am having would be much appreciated. Thanks.
why are we able to use the dereference * operator for our array as reference?
The * in C means many things. It can mean the unary indirection ("contents of") operator, it can mean the binary multiplication operator and it can mean a pointer declaration. The int* stat is a pointer declaration.
Since you aren't using the * to dereference the contents of the pointer inside that function, I'm not quite sure what you are asking.
When you take the array name of your array in main(), it "decays" into a pointer to the first element. So what those function do, is to take a pointer by value. If you dereference the pointer by typing *stat = something; you access the actual array in main.
Should you do something weird like changing the pointer itself, for example stat++;, then it will not affect the address used in main. You passed the pointer itself by value, so the pointer is a local copy.
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
You can't really pass arrays by value in C or C++, without resorting to dirty tricks (storing them inside structs or classes). For example, had your function been written as void changeIndexStaticArrayMethod1(int stat[3]) it would still give you a pointer to the first element. It will not pass an array by value, as the syntax might trick you into believing.
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
Because num is the pointer itself, not its contents. In order to write code like that, you could pass the variable by reference int& num. Behind the lines this is really the same thing as passing a pointer, just with simplified syntax.
To understand the relation between pointers and arrays better, start by reading this whole chapter: http://c-faq.com/aryptr/index.html (C and C++ are identical when it comes to pointers).
Let me see if I can take a stab at this.
Pointers are simply address holders. Once you do int * ptr = myarray; --- what you are in tern doing is storing the address of the pointer my array into ptr --- array names are actually pointers to the first memory location in the array. You can use pointer arithmetic to get at everything else for example myarray +1 will point you to the next location or myarray[1].
Passing by value is not very useful when you need to modify your array. Passing in by reference is essentially making a pointer to the array and passing that. Since arrays like vectors are contiguous blocks of memory you can index through them rather easily.
As far as your example goes void changeStaticNumber(int* num){ num = 100; } will not work because what you are attempting to do is store 100 into the pointer's address. If you deference num and make it void changeStaticNumber(int* num){ *num = 100; } it will work because you are actually going one step further and accessing the data that num is pointing to. When you use &num it is essentially the same thing - & just gives you the address of something.
For example if you want to point a pointer to an int what you would do is
int num = 5;
int *ptr = #
at this point in time ptr has the same address in num. To print out the data in num or that ptr is pointing to you need to dereference or go one step further as I like to tell myself and dereference to so cout << *ptr;
In both changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 you are not passing an array there is no pass by reference (which only happens if the parameter type is a reference type -- i.e. with &). The parameter has type int * (pointer to int). You are passing a pointer to int by value. There is no "dereference operator" in either function.
ne is already an int *, so passing it is nothing special. arr is an int [3], an array, not a pointer. In C, when an array-of-T is used in a context that expects a pointer-to-T, it is implicitly converted (without you needing to do anything) to a pointer to its first element. So when you do, changeIndexStaticArrayMethod1(arr), the compiler gets a pointer to the first element of arr, and passes that to the function.
The [] operator works on pointers. a[i] is always guaranteed to be the same as *(a + i). Inside both the changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 functions, [] is used to access subsequent elements using a pointer to the first element.
The following is a small scale example of the problem I am facing. In the example below I use int pointers but in my own code I am really using a pointer to another class (a node class).
The problem appears to be that I am using a call by value pointer (if there is such a thing). I don't know, I thought pointers were by reference. I do need to be able to pass multiple pointers to the method and I do not really want to write a specific method for each pointer. When I run the code, of course, I get some kind of error because it is trying to access a pointer that has not been allocated.
I do not understand why it would not initialize the correct pointer if I pass the specific pointer I want.
Any help would be greatly appreciated.
#include <iostream>
using namespace std;
class Test {
private:
int *p1;
int *p2;
int sizeP1;
int sizeP2;
public:
int* getIntPointer() {return p1;}
void initializeP1(int *ip,int n){
sizeP1=n;
ip=new int[n];
for(int i=0;i<n;i++)
p1[i]=i;
}
void printP1() {
for(int i=0;i<sizeP1;i++)
cout<<p1[i]<<" ";
}
};
int main() {
Test t;
t.initializeP1(t.getIntPointer(),10);
t.printP1(); //this fails.. but why? How can I fix it?
return 0;
}
The problem is that you initialize ip and you fill p1
void initializeP1(int **ip,int n){
sizeP1=n;
*ip=new int[n];
for(int i=0;i<n;i++)
*ip[i]=i;
}
//call with p1
initializeP1(&p1, 10); // pass pointer to pointer so you can get return value.
The problem is that your function allocates memory to the copy of the pointer that is the argument - this copy is lost at function exit. Pass the pointer by reference instead by changing the function signature
void initializeP1(int* &ip,int n){
^
This way the allocated memory is still accessible and your pointer will point to it
Would it not simply be easier to change your initializeP1 function to something like:
int * initializeP1(int n)
{
sizeP1 = n;
p1 = new int[n];
for(int i = 0; i < n; ++i)
p1[i] = i;
return ip;
}
There are still problems with this however, such as the fact that you can call it repeatedly and cause big memory leaks.
It might be better to use a proper constructor for your class that does what initializeP1 did, like such:
Test(int n)
{
sizeP1 = n;
p1 = new int[n];
for(int i = 0; i < n; ++i)
p1[i] = i;
return ip;
}
Pointers are not passed by reference, no. Pointers are value types. You'd want to use a reference if you absolutely had to make it look like this, but it's an abuse of syntax and you should do it a different way instead.
The call to t.getIntPointer() returns a pointer that is not initialised to something sensible.
The call to initializeP1() is newing an array of ints.
But be careful, this allocated block of memory will not be freed until you tell it so by writing "delete [] p1;".
I have quite peculiar problem. I want initialize an array pointed by a void pointer to which memory is allocated using new as shown below.
const int ARRAY_SIZE = 10;
void InitArray()
{
int *ptrInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrInt[i] = 1; //OK
}
void *ptrVoid = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
*(int*)ptrVoid[i] = 1; //Culprit : I get a compiler error here
//(error C2036: 'void *' : unknown size)
}
}
Now, I want to initialize the elements of this array which is pointed by ptrVoid with say 1. How do I go about it? With this code I get a compiler error as shown in the code(I am using VS 2010). Any suggestions?
You have an order of operations problem (and an extra *). Try this inside your second loop:
((int *)ptrVoid)[i] = 1;
*(int*)ptrVoid[i] is *((int*)(ptrVoid[i])), and you're dereferencing too many times (the [] does a dereference).
Write ((int*)ptrVoid)[i] (or, better, static_cast<int*>(ptrVoid)[i]) then re-consider your use of void* at all.
You just need to parenthesize correctly and cast the void* to an int*, so that the compiler knows how many bytes to offset when you index it with [i].
for(int i=0; i<ARRAY_SIZE;i++)
{
((int*)ptrVoid)[i] = 1;
}
How about:
int* ptrVoidAsInt = new int[ARRAY_SIZE];
for(int i=0; i<ARRAY_SIZE;i++)
{
ptrVoidAsInt[i] = 1;
}
void* ptrVoid = ptrVoidAsInt;
But, one has to wonder what the meaning of either a void array or 1 initialised data is. Is this really an array of int or some other type that is going to be passed as a void* and then recast back to a typed array?