Hoping for a little C++ assistance - I'm very new to the topic. I'm attempting to dynamically create an array based on user input with a pointer, then pass the array to a function. But the pointer (and thus array) pass feels a little wrong because there is no dereferencing that occurs.
During/after passing, do we just treat the pointer as if it were any normally declared-and-passed array, without the need to dereference (*) anything? Or am I applying this incorrectly?
Pseudocode follows:
#include<iostream>
using namespace std;
void arrayFunc(int [], int); // << Note no indication of pointer pass
int main()
{
int *arrayPtr = 0; // Array pointer
int arrayElem = 0; // Number of elements in array
cout << "\nPlease enter the number of elements: ";
cin >> arrayElem;
arrayPtr = new int[arrayElem]; // Dynamically create the new array
arrayFunc(arrayPtr, arrayElem); // << Note no dereferencing or other indication of pointer
return 0;
}
void arrayFunc(int array[], int arrayElem) // << Same here - now it's just a plain old array
{
// All the functiony-bits go here, referencing array without the need to dereference
}
[EDIT] While the above code works, the following includes the fixes determined in the discussion below:
#include<iostream>
using namespace std;
void arrayFunc(int*, int); // Changed to pointer pass instead of []
int main()
{
int *arrayPtr = 0; // Array pointer
int arrayElem = 0; // Number of elements in array
cout << "\nPlease enter the number of elements: ";
cin >> arrayElem;
arrayPtr = new int[arrayElem]; // Dynamically create the new array
arrayFunc(arrayPtr, arrayElem);
return 0;
}
void arrayFunc(int* array, int arrayElem) // Passing a pointer now instead of []
{
// All the functiony-bits go here, referencing array without the need to dereference
}
You should pass the pointer in your function, because it describes the situation accurately i.e. you are passing a dynamically allocated memory. arrayPtr is essentially a pointer to the first element of the array. As a result, you do not need to worry about dereferencing it.
Change the function signature to:
void arrayFunc(int*, int);
Your attempt is correct. You are passing the array pointer by value. You can then dereference it as normal within arrayFunc
C is designed to pretend a pointer and an array are the mostly same thing. Lots of simple uses are easier because of that. But the concept gets much more confusing when you think about a pointer to an array. It feels like it shouldn't be the same thing as a pointer to the first element of that array, but in the common methods for allocating memory and using pointers, a pointer to an array really is just a pointer to the first element of the array.
I find it best to think of "pointer to first element of array of" as the normal meaning of * in C. The special case of pointing to a scalar object is effectively treating the scalar as the first (and only) element of an array of length 1.
Related
I get Segmentary fault with this code:
#include <iostream>
using namespace std;
int* arrayCreate(int length){
int *ew[length];
for (int i=0; i<length; i++)
{
*(ew[i])=i;
}
return ew[0];
}
int main(){
int *ptr=arrayCreate(7);
cout << *ptr << endl;
}
And when I tried to change this line
int *ew[length];
into
int *ew = new int[length];
I have error < indirection requires pointer operand ('int' invalid) >
Any one please explain the difference between these two declaration, why I get segmentary fault and how to fix it?
In the first version, you allocate array of pointers on the stack and return an element of that array - which is dead once the function finishes. Accessing this return value means undefined behaviour.
In the second version, you create array of ints (not pointers) on the heap. Thus the syntax error.
What you want is
int* arrayCreate(int length){
int* ew = new int[length];
for (int i=0; i<length; i++)
{
ew[i]=i;
}
return ew;
}
Or better yet, don't use new[], use std::vector, which manages memory for you:
#include <vector>
#include <numeric> //for std::iota
std::vector<int> arrayCreate(int length){
std::vector<int> v (length);
std::iota(v.begin(), v.end(), 0); //you can use your loop as well
return v;
}
int *ew[length];
Problem 1: The size of an array variable must be compile time constant. length is not a compile time constant. Thus, the program is ill-formed.
how to fix it?
If you need an array with dynamic size, you need to allocate dynamically. Simplest solution is to use std::vector.
why I get segmentary fault
Observation: The pointers in ew have indeterminate values. They don't point to any valid object.
*(ew[i])=i;
Problem 2: You indirect through a pointer stored in the array. Since you're indirecting through an invalid pointer, the behaviour of the program is undefined.
Ask yourself: What int object was ew[i] supposed to be pointing to?
how to fix it?
Don't read indeterminate values, and don't indirect through invalid pointers.
int *ew = new int[length];
Here, you create a dynamic array of integers. Array of integers is not an array of pointers. ew is a pointer to an integer. ew is not a pointer to a pointer.
*(ew[i])=i;
Here, you indirect through ew to access ith successor sibling, and then indirect through that sibling. But the first indirection results in an int object and you cannot indirect through an int.
how to fix it?
Don't try to indirect through an int.
Any one please explain the difference between these two declaration
int *ew[length] is an ill-formed and uninitialised array of pointers to int. int* ew is a single pointer to an int, in this case initialised with the address of a first element of a dynamic array of int.
To get memory for your array in C++ you should write:
int *ew = new int[length];
To return the pointer you should write:
return ew;
This means you return pointer to the beginning of array. It should be mentioned that a[i] <=> *(a + i). You can't write *(ew[i]) = i; to assign, but ew[i] = i; will work.
It should also be said that usage of raw pointers is deprecated in modern c++.
Well, first of all I want to know if the following is 'legal' or at least 'not evil'.
Second, I want to know what is happening internally to make it possible! it is amazing and quite strange, I know that a pointer may be perceived a an indirect way to access to an object by its memory address, so I suppose that is due to that, that a pointer can be redirected to point over both, dynamic objects and arrays even after its declaration and multiple assignments.
Example:
#include <iostream>
#include <cstring>
int main()
{
size_t size;
std::cout << "Enter a size for an array: ";
std::cin >> size;
/*Creating a pointer to a single dynamic string*/
std::string *pointer = new std::string();
pointer->append("Some text");
std::cout << pointer << std::endl;
delete pointer;
pointer = NULL;
/*setting it to be an array*/
pointer = new std::string[size];
for (size_t i = 0; i < size; i++)
pointer[i] = "Number :" + std::to_string(i);
std::cout << std::endl;
for (size_t i = 0; i < size; i++)
std::cout << pointer[i] << std::endl;
}
Many thanks.
Note:
I tried to repeat this creating a template class with a lambda inside (using typedef) and it did not worked.
The code has defined behavior and works fine. There is no problem with it, except that you are leaking the last allocation, which is not really optimal (but legal). Add a delete[] pointer; at the end.
The array version of new doesn't return the newly created array or a pointer or reference to it. Instead it returns a pointer to the first element in the newly created array.
pointer = new std::string[size];
After this pointer will point to the first std:.string of the newly created std::string[size] array. Just looking at pointer you won't know whether the std::string that it points to is part of an array or not.
This is why you can reference both arrays and single objects through the same pointer type. The same works with automatic arrays, which decay to pointers to their first element when assigned to a pointer.
This is also why you as the programmer need to remember which pointer points to a single object allocated with new and which one points to an array allocated with new[] and how long that array is (because in the former case you need to delete it with delete and in the latter with delete[]).
In practice you should not use raw new like this for that reason (and others). Instead use containers like std::vector if you need dynamically-sized arrays and std::unique_ptr if you need dynamically allocated single objects (although there is also a std::unique_ptr version for arrays).
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.
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.
I am trying to make a c++ program with a class which holds integers on the "heap" and has only one method, pop() which returns the first item in the class and removes it. This is my code so far:
#include <iostream>
using namespace std;
class LinkList {
int *values; //pointer to integers stored in linklist
int number; // number of values stored in linklist
public:
LinkList(const int*, int); // Constructor (method declaration)
int pop(); // typically remove item from data structure (method declaration)
};
LinkList::LinkList(const int *v, int n){
number = n;
*values = *v;
int mypointer = 1;
while (mypointer<n) {
*(values+mypointer) = *(v+mypointer);
mypointer++;
}
}
int LinkList::pop() {
if (number>0) {
int returnme = *values; //get the first integer in the linklist
number--;
values++; //move values to next address
return returnme;
}
else {return -1;}
}
int main() {
int test[] = {1,2,3,4,5};
LinkList l1(test,5);
cout << l1.pop() << endl;
LinkList l2(test,5);
cout << l2.pop() << endl;
return 0;
}
The issue is that its failing at the line *values = *v, if i remove the 4th and 5th lines from the main method, I no longer get this issue, so its go to be a memory management thing.
What I want to do is to get values to point to a continuous bit of memory with integers in. I have tried to use arrays for this but keep just getting random memory addresses returned by pop()
Background: normal I programming in java, I've only be using C/C++ for 2 months, I'm using eclipse IDE in ubuntu, I can make very basic use of the debugger but currently I dont have functioning scroll bars in eclipse so I can't do somethings if they dont fit on my screen.
You are dereferencing an uninitialized pointer (values) at the line *values = *v; which is undefined behavior (UB). What this line says is "get the integer that values points to and assign to it the value pointed by v". The problem with this logic is that values doesn't yet point to anything. The result of this UB is the crash that you receive.
There are many other problems with this code, such as passing a const int* to the constructor with the intent of modifying those values. The biggest problem is that this is not an actual linked list.
*values = *v;
You dereference the values pointer in this line before initializing it. This is the source of the later errors, and the non-errors in the first three lines of main are simply due to luck. You have to allocate space via values = new int[n] and deallocate it in the destructor via delete[] values. std::vector does this work in a clean and exception-safe way for you.
Perhaps the problem is that you're incrementing an integer - mypointer, rather than a a pointer. If the integer requires more than one byte of space, then this might lead to errors. Could you try declaring a pointer and incrementing that instead?
The values member variable is a pointer to uninitialized memory. Before you start copying numbers into it you have to point it to valid memory. For example:
LinkList::LinkList(const int *v, int n){
number = n;
values = new int[n]; // allocate memory
int mypointer = 0;
while (mypointer<n) {
*(values+mypointer) = *(v+mypointer);
mypointer++;
}
}
LinkList::~LinkList() {
delete values; // release memory
}
Also, why do you call this a linked list while in fact you are using a memory array to store your numbers?