C++ passing an array pointer as a function argument - c++

I'm trying to use pointers of arrays to use as arguments for a function which generates an array.
void generateArray(int *a[], int *si){
srand(time(0));
for (int j=0;j<*si;j++)
*a[j]=(0+rand()%9);
} //end generateArray;
int main() {
const int size=5;
int a[size];
generateArray(&a, &size);
return 0;
} //end main
But when I compile this this message appears:
cannot convert `int (*)[5]' to `int**' for argument `1' to `void generateArray(int**, int*)'

You're over-complicating it - it just needs to be:
void generateArray(int *a, int si)
{
for (int j = 0; j < si; j++)
a[j] = rand() % 9;
}
int main()
{
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
When you pass an array as a parameter to a function it decays to a pointer to the first element of the array. So there is normally never a need to pass a pointer to an array.

int *a[], when used as a function parameter (but not in normal declarations), is a pointer to a pointer, not a pointer to an array (in normal declarations, it is an array of pointers). A pointer to an array looks like this:
int (*aptr)[N]
Where N is a particular positive integer (not a variable).
If you make your function a template, you can do it and you don't even need to pass the size of the array (because it is automatically deduced):
template<size_t SZ>
void generateArray(int (*aptr)[SZ])
{
for (size_t i=0; i<SZ; ++i)
(*aptr)[i] = rand() % 9;
}
int main()
{
int a[5];
generateArray(&a);
}
You could also take a reference:
template<size_t SZ>
void generateArray(int (&arr)[SZ])
{
for (size_t i=0; i<SZ; ++i)
arr[i] = rand() % 9;
}
int main()
{
int a[5];
generateArray(a);
}

You do not need to take a pointer to the array in order to pass it to an array-generating function, because arrays already decay to pointers when you pass them to functions. Simply make the parameter int a[], and use it as a regular array inside the function, the changes will be made to the array that you have passed in.
void generateArray(int a[], int si) {
srand(time(0));
for (int j=0;j<*si;j++)
a[j]=(0+rand()%9);
}
int main(){
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
As a side note, you do not need to pass the size by pointer, because you are not changing it inside the function. Moreover, it is not a good idea to pass a pointer to constant to a parameter that expects a pointer to non-constant.

I'm guessing this will help.
When passed as functions arguments, arrays act the same way as pointers. So you don't need to reference them. Simply type:
int x[]
or
int x[a]
. Both ways will work. I guess its the same thing Konrad Rudolf was saying, figured as much.

This is another method . Passing array as a pointer to the function
void generateArray(int *array, int size) {
srand(time(0));
for (int j=0;j<size;j++)
array[j]=(0+rand()%9);
}
int main(){
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}

Related

Problem with function which create and return pointer to dynamic vector

I have to crate a function which gets a reference to int array as one of arguments. This function should creates a dynamic vector and returns its pointer.
When I compile this code I got err: "No matching function for call to 'func'".
I have no idea what's wrong.
Immediately, I would like to ask if I removed the dynamic vector from the memory correctly or should I write it differently?
#include <iostream>
#include <vector>
using namespace std;
vector<int> *func(int &, int);
int main() {
const int arrSize = 5;
int arr[arrSize] = {1, 3, 5, 7, 9};
vector<int> *ptr_vec = func(arr, arrSize);
delete ptr_vec;
}
vector<int> *func(int &arr, int size){
auto *newVec = new vector<int>;
for(int i = 0; i < size; i++) newVec[i].push_back(arr+i);
return newVec;
}
Thanks in advance
The first parameter of the function is a reference to a scalar object of the type int
vector<int> *func(int &, int);
You need to write
vector<int> *func( const int *, int);
Also in the for loop you have to write
for(int i = 0; i < size; i++) newVec->push_back(arr[i]);
In fact the for loop is redundant. Your function could look simpler as for example
vector<int> * func( const int *arr, int size )
{
return new std::vector<int> { arr, arr + size };
}
Pay attention to that there is no great sense to define the vector dynamically. The function can be declared and defined the following way
vector<int> func( const int *arr, int size )
{
return { arr, arr + size };
}

how to convert 'std::vector<double>' to 'double' in initialization

I'm trying to make quicksort program. I just couldn't understand why and how this error is coming. I've tried every method online but I'm unable to catch the issue. If I'm doing this with array in place of vector, I'm getting correct output but with vector error is coming.
My errors are:
.\quicksort.cpp:7:28: error: cannot convert 'std::vector<double>' to 'double' in initialization
double pivot = values[end];
.\quicksort.cpp:10:19: error: no match for 'operator<=' (operand types are 'std::vector<double>' and 'double')
if (values[i] <= pivot) {
How to convert the vector<double> to double then?
Here's my code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int partition(vector<double> *values, int start, int end) {
double pivot = values[end];
int pIndex = start;
for (int i=start; i<end; i++) {
if (values[i] <= pivot) {
swap(values[i], values[pIndex]);
pIndex++;
}
}
swap(values[pIndex], values[end]);
return pIndex;
}
void quicksort(vector<double> *values, int start, int end) {
if (start<end) {
int pIndex;
pIndex = partition(values, start, end);
quicksort(values, start, pIndex-1);
quicksort(values, pIndex+1, end);
}
}
int main() {
int n;
cin >> n;
vector<double> values(n);
for (int i = 0; i < n; i++) {
cin >> values[i];
}
quicksort(values, 0, n-1);
for (int j=0; j<n; j++) {
cout<<values[j]<<" ";
}
return 0;
}
How to rectify these errors?
References not pointers
int partition(vector<double>& values, int start, int end) {
void quicksort(vector<double>& values, int start, int end) {
If you used a pointer (but you shouldn't) the correct code would be
double pivot = (*values)[end];
Pointers are not the same as the things they are pointing to, you have to use * or -> to get at the object that a pointer points to. You don't have to do this with references.
You have a C++ compiler so use it, send Reference to your object instead of pointer:
void quicksort(vector<double> &values, const int start, const int end);
int partition(vector<double> &values, const int start, const int end)
And your compile time error gone, with pointer to the object you need to call your function like this:
quicksort(&values, 0, n - 1);
Because you need it's address (actually your pointer need it).
And you need to use operator[] of std::vector which is first need to get std::vector object from pointer to it:
double pivot = (*values)[end];
As you see it's ugly and could be complex, So it's better to use References instead of pointer in those situations.
Your partition and quicksort functions take pointers as parameters not reference values.
Your functions should be declared as such:
int partition(vector<double> &values, int start, int end)
void quicksort(vector<double> &values, int start, int end)
The reason you are getting the error is that since the values parameter is a pointer when you use the array accessor ([i]) it assumes that values is an array of vectors and returns a vector not a double.
you should pass vector<double>& to your function instead of vector<double>*, i.e. pass by reference instead of pass by pointer. If passing by pointer, then you need to access the elements of the vector with ->[index].

How do I initialise a const array struct field with the output of a function?

I have a struct that contains a const array, and would like to initialise it to specific values upon construction. Unfortunately, its contents depend on several parameters which are passed into the constructor as parameters, and require a function to compute the contents of the array.
What I'd ideally like to do looks something like this:
struct SomeType {
const unsigned int listOfValues[32];
unsigned int[32] processParameters(unsigned int parameter) {
unsigned int arrayValues[32];
for(int i = 0; i < 32; i++) {
arrayValues[i] = i * parameter;
}
return arrayValues;
}
SomeType(unsigned int parameter) : listOfValues(processParameters(parameter)) {
}
};
Of course there are several issues here (returning an array from a function is not possible, data type mismatches, etc). However, is there any way this is possible?
I've seen other similar questions suggest using a std::vector for this, but the heap allocation(s) this incurs is something my performance budget can't afford.
As Nathan suggested you should change the raw array with an std::array. This way you still have the benefit of stack allocation but now you can initialize from a copy.
using MyArray = std::array<unsigned int, 32>;
const MyArray listOfValues;
MyArray processParameters(unsigned int parameter) {
MyArray arrayValues;
for(int i = 0; i < 32; i++) {
arrayValues[i] = i * parameter;
}
return arrayValues;
}
I removed the const from the array data type since it's not necesary because your array is const already, also with const unsigned int you wouldn't be able to set the values of arrayValues at run time.
Does this serve your purpose? No heap allocations that I can see.
struct SomeType {
const unsigned int *listOfValues;
const unsigned int * processParameters(unsigned int parameter) {
for(int i = 0; i < 32; i++) {
_listOfValues[i] = i * parameter;
}
return _listOfValues;
}
SomeType(unsigned int parameter) :
listOfValues(processParameters(parameter))
{
}
private:
unsigned int _listOfValues[32];
};

Arguments passing vs. Variable declaration

What's the difference between passing an argument inside a function as a parameter and declaring the argument as a variable inside the function declaration block in function definition?
Example: Make use of my comments to get the gist of the question.
#include<iostream>
int max=0;
int t=0;
class stack
{
int s[10];
public:
void push(int);
void pop();
};
void stack::push(int y) //argument passed inside function parameter
{
if(t<=max);
{
s[t]=y;
t=t+1;
}
else
cout<<"Stack overflow";
}
void stack::pop()
{
int item; //variable declared inside function definition
if(t>=0)
{
t=t-1;
item=s[t+1];
}
}
One difference is that parameters are initialized by the caller but local variables have to be initialized by the function.
int somefunc(int arg)
{
int local = 0;
…
return local + arg;
}
When the function is called:
int x = somefunc(23);
the variable arg in the function is initialized with the value 23 by the calling code. However, the local variable local has to be explicitly initialized (in this case with the = 0; if it was a class type, by an appropriate constructor). Local variables of built-in types such as int that are not explicitly initialized get a quasi-random value.
One difference is in how arrays are interpreted:
// returns nonzero iff array1 equals {1, 2, 3}
int func(int array1[], size_t size1)
{
int array2[] = {1, 2, 3};
return size1 == sizeof(array2) && memcmp(array1, array2, size1) == 0;
}
While array2 is an array of 3 integers, array1 is an array of unknown size, which is why we usually pass a second parameter for the size. This is because of arrays "decay to pointers" when passed into functions like this. You can read about it here: What is array decaying?
There are fancier techniques for dealing with this in C++ using value templates for the array size, but the above is true of C and most C++ code in the wild too.
Other than arrays, C types used in function parameters behave pretty much the same as C types used in local variables.
The arguments is passed by calling that function. so caller decides what should be passed.
functions decides what should it accept.
for example:
main()
{
int i=0;
int k=i;
for (int j=i; j `enter code here`< n; j++)
{
}
}
is same as
main()
{
int i=0,k;
for (int j=k=i; j < n; j++)
{
}
}
but this
main()
{
int i=0,k;
for (int j=i; j < n; j++)
{
k=i;
}
}
is totally different.

C++, Passing a 2D array on stack to function by reference

void build() will create a 2D array whose size is determined at run time and pass it to modify() by reference.
void modify() will make some change of the array.
.h file:
void modify(______, int mySize);
void build(int size);
in .cpp file:
void modify(______, int mySize) {
for (int i = 0; i < mySize; i++)
for (int j = 0; j < mySize; j++)
myArray[i][j] = false;
}
void build(int size) {
bool myArray[size][size];
modify(______, size);
}
Can someone tell me what to put in these blanks? I tried many way to cast myArray but still not working. Thank you so much!
First, note that variable length arrays (VLAs) are not standard C++. The fact that this line compiles is due to a GCC compiler extension:
bool myArray[size][size];
It simply isn't valid C++. The dimensions of your array need to be compile time constants, yet here you're using arguments passed to your function build.
Anyway, to pass a VLA to a function, you have to continue using compiler extensions. However, as far as I've tested, these only work when compiling as C. The first option uses an extension that allows parameters to be used in other parameter declarations:
void modify(int mySize, bool array[][mySize]);
The second option, if you want mySize to be the second argument, also uses a compiler extension allowing forward declarations of parameters:
void modify(int mySize; bool array[][mySize], int mySize);
Here int mySize; is a parameter forward declaration.
Nonetheless, you really shouldn't be using variable length arrays. You can dynamically allocate arrays of variable length, like so:
void modify(bool** array, int mySize);
void build(int size) {
bool** myArray = new bool*[size];
for (int i = 0; i < size; i++) {
myArray[i] = new bool[size];
}
modify(myArray, size);
}
However, this is still not a recommended practice in C++. You should avoid dynamic allocation unless you really need it, and when you do need it you should manage it in some way. Here, you would need to remember to delete[] each element of myArray and myArray itself.
What you should really be using is the standard containers. A std::vector<std::vector<bool>> would suit you well here:
void modify(std::vector<std::vector<bool>>& array);
void build(int size) {
std::vector<std::vector<bool>> myArray(size, std::vector<bool>(size));
modify(myArray);
}
Now you don't even have to pass along the size.
Use it this way:
void modify(bool**& myArray, const int mySize)
{
for (int i = 0; i < mySize; i++)
for (int j = 0; j < mySize; j++)
myArray[i][j] = false;
}
void build(const int size)
{
// create the array
bool** myArray = new bool*[size];
for (int i=0; i<size; i++)
myArray[i] = new bool[size];
modify(myArray, size);
// release the array
for (int i=0; i<size; i++)
delete[] myArray[i];
delete[] myArray;
}