I have a working code for a function which takes a character and a number and forms a string by duplicating that character that number of times. Here is a piece that works perfectly fine.
char * buildstr(char c, int n)
{
char * pc = new char[n+1];
for (int i = 0; i < n; ++i)
{
*(pc+i) = c;
}
*(pc+n) = '\0';
return pc;
}
But if I use another logic where I directly increment the pointer itself directly then I get an error when I free up the memory in the main function using delete [].
What could be my problem ?
Thanks,
char * buildstr(char c, int n)
{
char * pc = new char[n+1];
for (int i = 0; i < n; ++i)
{
*pc = c;
pc++;
}
*(pc) = '\0';
return pc;
}
The problem is that you're returning the incremented pointer. delete[] has to be invoked with a pointer value that was returned by a call to new[], otherwise you get undefined behaviour. The same applies to calls to free and pointers returned by malloc, calloc etc.
In the second example, you are incrementing the value of the pointer. When you try to delete it, it is pointing to the last position of the array.
This way, when you call delete[] on it, it crashes as it expects pc to point to the address that was originally allocated using new[].
I encourage you to use the first approach as you will be able to keep track of the base address through the lifetime of pc. Moreover, I think it would be easier for you to do this using array notation.
Consider using:
pc[i] = c;
instead of
*(pc+i) = c;
As it is more idiomatic and easy to read. If you are simply exercising your pointer arithmetic, stick to the first approach that you described.
In the first function let's say that your pointer start at 0x00100.
when you do the loop you get to the next adress so for exemple let's say 4 loop:
0x00100
0x00101
0x00102
0x00103
but at the end you return the pointer on the 0x00100 beceause you used index *(pc+i) where i is the index, so it is good.
Now on the second function you are doing the same exept that your are moving your pointer itself without index so you return your pointer at the last adress
0x00103
That is wy your second function doesn't work
Related
I'm currently learning pointer. And when I create a pointer to an array with int type, I found that I can directly index the pointer without deferencing the pointer and the compiler still output exact items in my array. I do not understand why this works and why we don't need to first deference the pointer.
Code that without dereference
int arraySize = 5;
int* theArray = new int[arraySize];
for(int i = 0; i < 5; i++)
{
theArray[i] = i;
}
for (int i = 0; I < 5; i++)
{
std::cout << theArray[i] << std::endl;
}
And this gives me the output
Output without derefercing
However, when I wrote like this:
for (int i = 0; i < 5; i++)
{
(*theArray)[i] = i;
}
My compiler says that: Error: expression must have pointer-to-object type. (I'm using Visual Studio 2013.)
Any help would be appreciated.
Code that without dereference
[ code ]
That's incorrect. You are most certainly dereferencing your pointer:
theArray[i] = i;
That's a pointer dereference. The [] operator dereferences the pointer. This is equivalent to:
*(theArray+i) = i;
As you know, adding or subtracting a value to a pointer advances or decrements the pointer, producing a new pointer value, and then the pointer gets dereferenced.
Also:
*p = q;
is equivalent to
p[0] = q;
The [] operator is just a shorthand for adding an offset to a pointer, and dereferencing the resulting pointer with the * operator. The end result is exactly the same.
I do not understand why this works and why we don't need to first deference the pointer.
The first version is correct:
for(int i = 0; i < 5; i++)
{
theArray[i] = i;
}
because theArray[i] is actually *(theArray + i) - essentially pointer arithmetic is equivalent to array index.
On the other hand, the 2nd version is incorrect:
for (int i = 0; i < 5; i++)
{
(*theArray)[i] = i;
}
That's because (*theArray)[i] is actually pointer to array (not the array itself), and so it caused a type mismatch as the compiler already suggested.
A few other answers correctly say that *(theArray + i) is equivalent to theArray[i]. But the point I think you missed when learning is that unlike most objects a pointer to an array is not a pointer to the array that is then dereferenced, and then array logic, it is only a pointer to the first element of the array. That's why this:
int *myIntPointer = new int[5];
is NEARLY the same as this:
int myIntArray[5]; // "True" array on the stack
But you can also point it at something else:
int myInt = 10;
delete [] myIntPointer;
myIntPointer = &myInt;
It's also why doing the follow CAN give a compiler warning, but can also work (depends on the compiler):
myIntPointer = myIntArray; // Sometimes works, sometimes doesn't, compiler dependent
That's because allocating an array with new int[size] returns a pointer to an int not a pointer to an "array" type.
It's a weird corner case of C/C++ that arrays and pointers interact this way. You also run into it if you try and pass one of the "true" arrays into a function.
theArray[i] literally corresponds to *(theArray + i) so it already dereferences the pointer.
Indeed when you try to call operator[] on *theArray it yields you an error because it expects a pointer, not a real object.
You're actually asking the wrong question for your misunderstanding — you should be asking why you can write
int* theArray = new int[arraySize];
In c++, array types are not like other types, and have a number of special cases and rules that make them behave differently from other types. In particular, new T[N] does not return a "pointer to an N-long array of T", it returns a "pointer to T". (specifically, to the first element of the newly created array)
For a more mindboggling example of this, observe:
typedef int T[5];
T* p = new T; // this does not compile
int* q = new T; // this does compile
I am a bit confused when you pass NULL as a parameter
for example
int* array_create( int* array,size)
{
array = new int[size];
return array;
}
int main()
{
int* array = array_create(NULL,10);//can we pass NULL in this case?
delete[] array;
return 0;
}
I know the example is kinda stupid, but I am wondering if we can pass NULL as the parameter when the function assigns some heap memory to a pointer and returns it?
When you call your function like this...
int* array = array_create(NULL,10);//can we pass NULL in this case?
...you are getting behaviour like:
int* array_create(...)
{
int* array = NULL;
size_t size = 10; // using size_t as you'd missed any type
array = new int[size];
return array;
}
Ultimately, array is initialised to NULL then shortly afterwards overwritten with the value returned by new, so the initialisation serves no purpose.
For this code, there was simply no point passing an array argument... you could have created a local variable directly:
int* array_create(size_t n)
{
int* array = new int[size];
return array;
}
...or even...
int* array_create(size_t n)
{
return new int[size];
}
I am wondering if we can pass NULL as the parameter when the function assigns some heap memory to a pointer and returns it?
This requirement doesn't make much sense, as the two things are unrelated. You can pass whatever you like, and return whatever you like.
More commonly, a function might do something like:
void dump_bytes(std::ostream& os, unsigned char* p, size_t n)
{
if (p)
for (size_t i = 0; i < n; ++i)
os << static_cast<int>(p[i]) << ' ';
}
In dump_bytes, specifying a p value of NULL would fail the if (p) condition, ensuring the function didn't invoke undefined behaviour by dereferencing via a NULL pointer, even if n was not 0.
Just summarizing from the comments:
Yes, it is completely valid, but in Your example it is completely useless (you know that)
Some examples of this in real code:
In OpenGL you can tell the API if the data you want is coming from is from a buffer:
glBufferData(..., nullptr);
But wait! That's not null, that's nullptr?
Well in a c++11 compiler nullptr is a better option. Because NULL often usually resolves to 0, a version of the method that takes an int instead of a pointer the compiler will choose the int.
Here's some more data on that:
http://en.cppreference.com/w/cpp/language/nullptr
Also, if you want to edit an array, you should pass a pointer to a pointer.
A very general question: I was wondering why we use pointer to pointer?
A pointer to pointer will hold the address of a pointer which in turn will point to another pointer. But, this could be achieved even by using a single pointer.
Consider the following example:
{
int number = 10;
int *a = NULL;
a = &number;
int *b = a;
int *pointer1 = NULL;
pointer1 = b; //pointer1 points to the address of number which has value 10
int **pointer2 = NULL;
pointer2 = &b; //pointer2 points to the address of b which in turn points to the address of number which has value 10. Why **pointer2??
return 0;
}
I think you answered your own question, the code is correct, what you commented isn't.
int number = 10; is the value
int *pointer1 = b; points to the address where int number is kept
int **pointer2 = &b; points to the address where address of int number is kept
Do you see the pattern here??
address = * (single indirection)
address of address = ** (double indirection)
The following expressions are true:
*pointer2 == b
**pointer2 == 10
The following is not!
*pointer2 == 10
Pointer to pointer can be useful when you want to change to what a pointer points to outside of a function. For example
void func(int** ptr)
{
*ptr = new int;
**ptr = 1337;
}
int main()
{
int* p = NULL;
func(&p);
std::cout << *p << std::endl; // writes 1337 to console
delete p;
}
A stupid example to show what can be achieved :) With just a pointer this can not be done.
First of all, a pointer doesn't point to a value. It point to a memory location (that is it contains a memory address) which in turn contains a value. So when you write
pointer1 = b;
pointer1 points to the same memory location as b which is the variable number. Now after that is you execute
pointer2 = &b;
Then pointer2 point to the memory location of b which doesn't contains 10 but the address of the variable number
Your assumption is incorrect. pointer2 does not point to the value 10, but to the (address of the) pointer b. Dereferencing pointer2 with the * operator produces an int *, not an int.
You need pointers to pointers for the same reasons you need pointers in the first place: to implement pass-by-reference parameters in function calls, to effect sharing of data between data structures, and so on.
In c such construction made sense, with bigger data structures. The OOP in C, because of lack of possibility to implement methods withing structures, the methods had c++ this parameter passed explicitly. Also some structures were defined by a pointer to one specially selected element, which was held in the scope global to the methods.
So when you wanted to pass whole stucture, E.g. a tree, and needed to change the root, or 1st element of a list, you passes a pointer-to-a-pointer to this special root/head element, so you could change it.
Note: This is c-style implementation using c++ syntax for convienience.
void add_element_to_list(List** list, Data element){
Data new_el = new Data(element); // this would be malloc and struct copy
*list = new_el; //move the address of list, so it begins at new element
}
In c++ there is reference mechanismm and you generally you can implement nearly anything with it. It basically makes usage of pointers at all obsolete it c++, at least in many, many cases. You also design objects and work on them, and everything is hidden under the hood those two.
There was also a nice question lately "Why do we use pointers in c++?" or something like that.
A simple example is an implementation of a matrix (it's an example, it's not the best way to implement matrices in C++).
int nrows = 10;
int ncols = 15;
double** M = new double*[nrows];
for(unsigned long int i = 0; i < nrows; ++i)
M[i] = new double[ncols];
M[3][7] = 3.1416;
You'll rarely see this construct in normal C++ code, since C++ has references. It's useful in C for "passing by reference:"
int allocate_something(void **p)
{
*p = malloc(whatever);
if (*p)
return 1;
else
return 0;
}
The equivalent C++ code would use void *&p for the parameter.
Still, you could imagine e.g. a resource monitor like this:
struct Resource;
struct Holder
{
Resource *res;
};
struct Monitor
{
Resource **res;
void monitor(const Holder &h) { res = &h.res; }
Resource& getResource() const { return **res; }
}
Yes, it's contrived, but the idea's there - it will keep a pointer to the pointer stored in a holder, and correctly return that resource even when the holder's res pointer changes.
Of course, it's a dangling dereference waiting to happen - normally, you'd avoid code like this.
I'm trying to call a function written in C which passes in a pointer to an array.
In C++ I have the following:
double* x = new double[10];
populateArray(x);
In C:
void populateArray(double* vars);
{
vars = (double*) malloc(10*sizeof(double));
int i;
for(i = 0; (i < 10); i++)
{
vars[i] = 1*20;
}
}
However, when I try to output the contents of x inside the C++ code, the result is always 0?
Problem arises because you are changing local variable vars.
Change to:
double* x; //you don't need to allocate here if you are allocating later
populateArray(&x);
And:
void populateArray(double** vars)
{
*vars = malloc(10*sizeof(double)); //also no need to cast malloc
int i;
for(i = 0; (i < 10); i++)
{
(*vars)[i] = 1*20;
}
}
void populateArray(double* vars);
{
vars = (double*) malloc(10*sizeof(double)); // <---- remove this line completely
The problem is you're ignoring the vars you were given and creating a brand new buffer for it.
Worse, that buffer pointer gets lost when this function returns, causing a memory leak.
Just use the vars you were given -- delete the line indicated above.
Short answer: Remove the malloc call inside the function.
Slightly longer answer:
You're changing the value of the vals pointer to another newly allocated memory -- thus, the argument you pass in gets unused (and thus is never populated).
The result being always 0 is a coincidence, it could be anything (or you could end up with nasal demons) because you're then reading uninitialized memory, which is undefined behavior.
This of it as this, if you remove the call:
vals = new double[10];
vals = malloc(10 * sizeof(double));
The first value is overwritten.
I am stuck in this problem: how to resize, inside a function, a dynamically allocated array, which has been passed, to the function, by reference.
I tried this, along with countless variations on this very approach. Of course this is just an example, it should print "john" ten times, expanding an array passed by reference that originally had only size 1 ( ie only 1 name ).
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int NumLast=-1;
int Surname(string *MyData)
{
for (int i=0; i<10 ; i++)
{
NumLast++;
string *Temp = new string[NumLast+1]; // temporary array
for (int jjj=0; jjj<NumLast; jjj++)
Temp[jjj]=MyData[jjj];
delete[] MyData;
MyData=Temp;
MyData[NumLast]="John";
}
return 0;
}
void main()
{
string *Data = new string[1]; // inizializza l'array
Surname(&*Data);
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
system("pause");
}
You have to pass by reference. You are passing by value. You are getting
&*Data = Data
The value of the address of what is pointed to Data = Data
Then you pass it by value to Surname. Anything Surname does to it won't affect Data in main.
int Surname(string *MyData) // This will take a copy of whatever you passed in to MyData
should be (The reference operator should be on the function definition.)
int Surname(string*& MyData)
^^
And the call will be
void main()
{
string *Data = new string[1];
Surname(Data); // The function will take a reference of data.
Buy may I ask why you are allocating in a loop?
Looks like std::vector is best solution for your case.
If you really need to reallocate manually, think about old school malloc(), free(), realloc() interface. Main thing to remember is to not intermix it with C++ new/delete interface despite usually new / delete is implemented using malloc() / free().
If you need array you should pass not array but pointer (or reference) to array (double pointer). In case of std::vector it is enough to pass reference to it.
Yet another argument to use reference to std::vector - in case of pointer to array caller should be notified somehow what is new array size.
I decided to try and go through your code line by line and point out some of the issues and highlight what's going on. I will start from your main function:
void main()
{
string *Data = new string[1]; // inizializza l'array
Surname(&*Data);
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
}
OK, so what this code does is allocate one string and save the pointer to it in a variable called Data.
Then it dereferences Data, thus, getting back a string and then gets the address of of that string (i.e. gets back the same thing as Data).
In other words this code:
Surname(&*Data);
does exactly the same as this code:
Surname(Data);
So, now let's take a look at Surname:
int Surname(string *MyData)
{
for (int i=0; i<10 ; i++)
{
NumLast++;
string *Temp = new string[NumLast+1]; // temporary array
for (int jjj=0; jjj<NumLast; jjj++)
Temp[jjj]=MyData[jjj];
delete[] MyData;
MyData=Temp;
MyData[NumLast]="John";
}
return 0;
}
This weird function accepts a pointer to a string and loops 10 times doing stuff. Let's see what happens in the first iteration of the loop...
First, it increments NumLast (which goes from -1 to 0). Then it allocate an array of strings, of length NumLast + 1 (i.e. of length 1). So far so good.
Now you might think the function would enter the for loop. But it won't: remember that at that point NumLast and jjj are both 0 and therefore, jjj < NumLast is false.
The code will then delete[] MyData (that is, it will delete whatever MyData points to), set MyData to point to the temporary array allocated earlier in the loop, and then set the first element (at index 0) to the string "John".
In the second iteration of the loop, the function again increments NumLast (which will now be 1). It will again allocate an array of strings, this time of length 2.
The loop will be entered this time. It will copy the first entry from MyData into the first entry from Temp. And it will exit.
Again, MyData will be deleted, and the pointer will be made to point to the newly allocated array.
Rinse. Lather. Repeat.
Finally, the function will exit. We go back to main, which will now execute this bit of code:
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
Wait a second though. Where does Data point to? Well... it points to data that has already been deleted long ago. Why?
Well, Surname received a copy of the Data pointer. When it called delete[] MyData it deleted the array that it MyData pointed to (which was the same array that Data pointed to). When Surname later did MyData=Temp all that changed was MyData (the copy of the pointer local to the function Surname) and Data (the pointer in main) was unaffected and continued to point to the now deleted memory.
Others have explained how you can get the effect you want and I won't repeat what they wrote. But I would urge you to sit down and think about what Surname does and how the code is unclear and confusing and how it can be rewritten so that it's easier to understand and less prone to error.
For those who in the future will need the solution to the same problem here is the amended code:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int NumLast=-1;
int Surname(string *&MyData)
{
for (int i=0; i<10 ; i++)
{
NumLast++;
string *Temp = new string[NumLast+1];
for (int jjj=0; jjj<NumLast; jjj++)
Temp[jjj]=MyData[jjj];
delete[] MyData;
MyData=Temp;
MyData[NumLast]="franci";
}
return 0;
}
void main()
{
string *Data = new string[1]; // inizializza l'array
Surname(Data);
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
system("pause");
}