c++ pointers & arrays - c++

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int width = 100;
int height = 100;
float cam[] = {-1.1,-1.0,1.2};
float D[] = {0.2,0.2,-0.2};
float U[] = {0.0,1.0,0.0};
float* cross(float* v1,float* v2)
{
float el1[] = {(v1[1]*v2[2]-v1[2]*v2[1]),(v1[2]*v2[0]-v1[0]*v2[2]),(v1[0]*v2[1]-v1[1]*v2[0])};
return el1;
}
float* neg3(float* v)
{
float arr[3];
for(int i=0;i<3;i++)
arr[i] = 0.0-(v[i]);
return arr;
}
/*
float* cam_space(float* p)
{
float* e1 = cross(D,U);
float* e2 = cross(D,cross(U,D));
float* e3_n = D;
float ar[4];
ar[0] = e1[0]*p[0]+e1[1]*p[1]+e1[2]*p[2];
ar[1] = e2[0]*p[0]+e2[1]*p[1]+e2[2]*p[2];
ar[2] = -(e3_n[0]*p[0]+e3_n[1]*p[1]+e3_n[2]*p[2]);
ar[3] = p[3];
return ar;
}
*/
float* translate(float* p,float* v)
{
float arr1[3];
for(int i=0;i<=2;i++)
arr1[i] = p[i] + v[i];
return arr1;
}
int main()
{
float* poi;
poi = cam; //undo later
float* nc;
nc = neg3(cam);
cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl;
float arbit[3] = {0.1,0.1,0.1};
float* temp1;
temp1 = translate(poi,arbit);
//float* temp2;
//temp2 = cam_space(temp);
cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl;
cout<<" "<<poi[0]<<" "<<poi[1]<<" "<<poi[2]<<endl;
cout<<" "<<temp1[0]<<" "<<temp1[1]<<" "<<temp1[2]<<endl;
return 0;
}
As you can see, I am outputting nc twice. But both the values differ. The second time nc is displayed, it actually shows the temp1 value, and temp1 actually shows garbage values.
Any help?

float* translate(float* p,float* v)
{
float arr1[3];
for(int i=0;i<=2;i++)
arr1[i] = p[i] + v[i];
return arr1;
}// arr1 ceases to exist from this point.
You are returning the reference of a local variable, arr1. It resides on stack and gets de-allocated on the return of function call. But you are holding a reference to it which is yielding you garbage values. Instead new new[] arr1 and return it. Remember to delete[] it when you are done.

You are returning pointers to local variables left right and centre. Those variables go out of scope at the end of the function body, and the result is undefined behaviour.
A nice way of handling array-modifying functions is to pass the array as a parameter:
void modify_me(float arr[]) // or `modify_me(float * arr)`, same thing
{
arr[0] = 0.5;
arr[1] = -2.25;
}
int main()
{
float myarray[2];
modify_me(myarray); // now myarray[0] == 0.5, etc.
// ...
}
Since you're in C++, you could even use template magic:
template <unsigned int N>
void modify_me(float (&arr)[N])
{
static_assert(N == 3, "You're doing it wrong!"); // C++11 feature
arr[0] = /* ... */
}
Now you get a compile-time error if you try to call this with anything that's not an automatic array of size 3.

Instead of returning pointers to local variables you should return values.
Consider this:
struct V3 { float data[3]; }
V3 neg3(V3 v)
{
for(int i=0;i<3;i++)
v.data[i] = -v.data[i];
return v;
}

translate() returns a local pointer (converted from array type). So what temp1 is referring to, doesn't exist after the function translate() returns.
Same is the case with neg3() also.
If you're using C++, then std::vector<float> will solve all such problem.
You could write this:
std::vector<float> translate(const std::vector<float> & p, const std::vector<float> & v)
{
std::vector<float> vf(3);
for(int i=0;i <3;i++)
vf[i] = p[i] + v[i];
return vf; //semantically, it returns a copy of the local object.
}
Similarly, use std::vector whereever you're using float[3]. And don't use global variables.

Related

return 2D array in C++

I am kind of new to C++ and I was doing a physics simulation in python which was taking forever to finish so I decided to switch to C++, and I don t understand how to make a function which will return a 2D array (or 3D array)
#include <iostream>
#include <cmath>
// #include <complex> //
using namespace std;
double** psiinit(int L, int n, double alpha){
double yj[400][400] = {};
for (int j = 0; j < n; j++)
{
double xi[400] = {};
for (int i = 0; i < n; i++)
{
xi[i] = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
};
yj[j] = xi;
};
return yj;
}
int main(){
int L = 10;
int n = 400;
int nt = 200*n;
double alpha = 1;
double m = 1;
double hbar = 1;
double x[n] = {};
double y[n] = {};
double t[nt] = {};
double psi[nt][n][n] = {};
psi[0] = psiinit(L, n, alpha);
cout << psi <<endl;
return 0;
}
I have look for answers but it doesn't seems to be for my kind of problems
Thanks
If you're new to c++ you should read about the concepts of heap and stack, and about stack frames. There are a ton of good resources for that.
In short, when you declare a C-style array (such as yj), it is created in the stack frame of the function, and therefore there are no guarantees about it once you exit the frame, and your program invokes undefined behavior when it references that returned array.
There are 3 options:
Pass the array to the function as an output parameter (very C-style and not recommended).
Wrap the array in a class (like std::array already does for you), in which case it remains on the stack and is copied to the calling frame when returned, but then its size has to be known at compile time.
Allocate the array on the heap and return it, which seems to me to best suit your case. std::vector does that for you:
std::vector<std::vector<double>> psiinit(int L, int n, double alpha){
std::vector<std::vector<double>> yj;
for (int j = 0; j < n; j++)
{
std::vector<double> xi;
for (int i = 0; i < n; i++)
{
const int value = exp(-(pow((i-(L/4)), 2) + (pow((j-(L/4)), 2)))/alpha) / (sqrt(2)*3.14159*alpha);
xi.push_back(value);
}
yj.push_back(xi);
}
return yj;
}
If you're concerned with performance and all of your inner vectors are of a fixed size N, it might be better to use std::vector<std::array<double, N>>.
Either make a wrapper as said above, or use a vector of vectors.
#include <vector>
#include <iostream>
auto get_2d_array()
{
// use std::vector since it will allocate (the large amount of) data on the heap
// construct a vector of 400 vectors with 400 doubles each
std::vector<std::vector<double>> arr(400, std::vector<double>(400));
arr[100][100] = 3.14;
return arr;
}
int main()
{
auto arr = get_2d_array();
std::cout << arr[100][100];
}
Your understanding of arrays, pointers and return values is incomplete. I cannot write you a whole tutorial on the topic but I recommend you read up on this.
In the mean time, I recommend you use std::vector instead of C-style arrays and treat your multidimensional arrays as 1D vectors with proper indexing, e.g. cell = vector[row * cols + col]
Something like this:
#include <cmath>
// using std::exp, M_PI, M_SQRT2
#include <vector>
std::vector<double> psiinit(int L, int n, double alpha) {
std::vector<double> yj(n * n);
double div = M_SQRT2 * M_PI * alpha;
for (int j = 0; j < n; j++)
{
double jval = j - L/4;
jval = jval * jval;
for (int i = 0; i < n; i++)
{
double ival = i - L/4;
ival = ival * ival;
yj[j * n + i] = std::exp(-(ival + jval) / alpha) / div;
}
}
return yj;
}
Addendum: There are also specialized libraries to support matrices better and faster. For example Eigen
https://eigen.tuxfamily.org/dox/GettingStarted.html
heap allocating and returning that pointer will also work...
instead of
double yj[400][400] = {};
do,
double** yj;
yj = new double*[400];
yj[i] = new double[400];
then just,
return yj;

Segmentation fault error with 2D arrays C++

I dunno why I have segmentation error when I'm trying to set or get any element from created array!!
Here it is in line with A[0][0] = 1;
I'm using g++ 9.3.0. What do I do wrong?
#include <iostream>
#define SIMULATIONS 30
using namespace std;
void init_matrixes(int a_rows, int b_cols, int vec_len, double **A, double **B, double **C)
{
A = new double *[a_rows];
B = new double *[vec_len];
C = new double *[a_rows];
for (int i = 0; i < a_rows; i++)
{
A[i] = new double[vec_len];
C[i] = new double[b_cols];
}
for (int i = 0; i < vec_len; i++)
B[i] = new double[b_cols];
}
int main()
{
double s;
int t1, t2, a_rows, b_cols, vec_len;
for (auto v : {50, 100})
{
a_rows = v;
b_cols = v;
vec_len = v;
for (int i = 0; i < SIMULATIONS; i++)
{
double **A, **B, **C;
init_matrixes(a_rows, b_cols, vec_len, A, B, C);
A[0][0] = 1; // error here
}
std::cout << "size = " << v<< " time = " << s / SIMULATIONS << endl;
}
return 0;
}
TL;DR version
Use std::vector or a matrix class like the one described here. This will eliminate the need for special allocation and deallocation functions thanks to the magic of RAII.
What went wrong?
A pointer is just another variable, but one that can contain the location of another object. Like any other variable, the pointer will be will be passed by value into a function and copied by default. The object pointed at is passed by reference (by way of pointer), but the pointer itself is passed by value.
double **A defines A as a pointer to a pointer to a double that is a copy of the pointer provided by the caller.
A = new double *[a_rows];
updates the copy and the caller is none-the-wiser. As a result all of the memory allocated is leaked at the end of the function because the local A goes out of scope.
So How do I fix it?
Pass the pointers by reference.
void init_matrixes(int a_rows,
int b_cols,
int vec_len,
double ** & A,
double ** & B,
double ** & C)
A, B, and C, are passed by reference (references this time) and are no longer copies.
A = new double *[a_rows];
Updates the pointer provided by the caller, and the caller now has a pointer pointing to valid storage.

A Function returning an array from 1 int input

I made a function the returns an array like so
void array_function(int i){
int* a = NULL;
a = new int[3];
a = {i-1, i, i+1};
return a;
}
Now I want to call this function in the a new function
int main(){
int n = 3
for(int i = 0; i < n; i++){
//call the function
}
}
I am not sure how I can call the function to give me the array, any help will be appreciated
Use std::array instead. It has more friendly value semantics:
#include <array>
std::array<int, 3> array_function(int const i) {
return {{ i - 1, i, i + 1 }};
}
int main() {
for(int i = 0; i < 3; i++){
auto arr = array_function(i);
// Use array
}
}
First your function is void, which translates as no-return-function. Make it return int* like
int* array_function(int i)
Now, to call the function you need to assign it to a temporary variable, which you can do work and then you should delete it. Full code:
int* array_function(int i){
int* a = new int[3];
a[0] = i-1, a[1] = i, a[2] = i+1;
return a;
}
int main(){
int n = 3;
for(int i = 0; i < n; i++){
int* a = array_function(i); // if you are going to do something with this array, which you will
// some work with a
delete[] a; // delete it to release memory from heap, everytime you do new, you should use delete at the end of your program
}
}
You want something like this to create the array, since the method in your question does not have a return type assigned (void means that it returns nothing), you have to define a return type for the method to work, in this case a pointer to an array:
int* array_function(int i){
int* a = NULL;
a = new int[3];
a = {i-1, i, i+1};
return a;
}
And then just store the result of the method in a local variable like this:
int* myArray = array_function(n);

How to reference a 2d pointer?

In my code I create a function outside of the main, which creates a 1D array and initializes to 0.
void create_grid(double *&y, int Npoints)
{
y = new double[Npoints];
for (int i = 0; i < Npoints; i++)
{
y[i] = 0;
}
}
If I didn't have the syntax of declaring in the function as double *&y I couldn't access the values of y.
I tried doing the same for a 2D array but i don't know the syntax. I tried &&**y and &*&*y but it didn't work. Does anyone know how to create a function outside of the main, which initializes a 2d dynamic array so I can use it in the main?
E.g.:
void create_grid_2D(double **&&y, int Npoints1, int Npoints2)
{
y = new double*[Npoints1];
for (int i = 0; i < Npoints1; i++)
{
y[i] = new double[Npoints2];
}
for (int i = 0; i < Npoints1; i++)
{
for (int j = 0; j < Npoints2; j++)
{
y[i][j] = 0;
}
}
}
int main()
{
int N = 10;
double **z;//correcting this line, i wrote z**
create_grid_2D(z, N, N);
delete[]z;
return 0;
}
C++ does not allow forming a pointer to reference or reference to reference. (And without a space between the characters, && is a single token meaning something entirely different.)
And your declaration double z**; is incorrect - you probably mean double **z;.
To write a function that takes the argument double **z by reference, you just want a reference to pointer to pointer:
void create_grid_2D(double **&y,int Npoints1,int Npoints2)
{
//...
}
Except don't use new and delete. Using them slightly wrong leads to memory leaks and bugs with dangling pointers and double deletes. For example, you tried to clean up your memory in main with delete []z;, but new-expressions were evaluated 11 times to your one delete-expression, so this misses out on deleting the row arrays z[0], z[1], ... z[9]. There's pretty much always a better and simpler way using std::unique_ptr, std::shared_ptr, std::vector, or other RAII (Resource Allocation Is Initialization) tools.
So I would change the function to:
void create_grid_2D(std::vector<std::vector<double>>& y,
unsigned int Npoints1,
unsigned int Npoints2)
{
y.assign(Npoints1, std::vector<double>(Npoints2, 0.0));
}
int main()
{
unsigned int N=10;
std::vector<std::vector<double>> z;
create_grid_2D(z, N, N);
// No manual cleanup necessary.
}
Or even use a return value rather than assigning an argument:
std::vector<std::vector<double>> create_grid_2D(
unsigned int Npoints1,
unsigned int Npoints2)
{
return std::vector<std::vector<double>>(
Npoints1, std::vector<double>(Npoints2, 0.0));
}
int main()
{
unsigned int N=10;
std::vector<std::vector<double>> z = create_grid_2D(N, N);
}
An easy trick to resolve/write such complicated references is (simplified version for the sake of this problem - it's a bit more complicated with braces present): start from the variable name and go to the left, step by step. In your case:
... y
y is ...
... & y
y is a reference ...
... *& y
y is a reference to a pointer ...
... **& y
y is a reference to a pointer to a pointer ...
double**& y
y is a reference to a pointer to a pointer to a double
So, the correct definition is:
void create_grid_2D(double**& y,int Npoints1,int Npoints2)
But as mentioned in the comments, please do really consider avoiding raw pointers in favor of std::vector and other standard containers.
So you want a reference on a pointer to a pointer.
2d pointer is int**, and the reference is int**&. That's what you want to use.
Then, you should a container or at least a smart pointer instead.
This approach would be a little different than what you currently have but basically you want a 2D grid and another name for this is simply a MxN Matrix! We can do this very easily with a simple template structure. This template class will hold all of the contents without having to put the data into dynamic memory directly. Then once you have your class object that you want to use we can then put that into dynamic memory with the use of smart pointers!
#include <iostream>
#include <memory>
template<class T, unsigned M, unsigned N>
class Matrix {
static const unsigned Row = M;
static const unsigned Col = N;
static const unsigned Size = Row * Col;
T data[Size] = {};
public:
Matrix() {};
Matrix( const T* dataIn ) {
fillMatrix( dataIn );
}
void fillMatrix( const T* dataIn );
void printMatrix() const;
};
template<class T, unsigned M, unsigned N>
void Matrix<T, M, N>::fillMatrix( const T* dataIn ) {
for ( unsigned i = 0; i < Size; i++ ) {
this->data[i] = dataIn[i];
}
}
template<class T, unsigned M, unsigned N>
void Matrix<T,M,N>::printMatrix() {
for ( unsigned i = 0; i < Row; i++ ) {
for ( unsigned j = 0; j < Col; j++ ) {
std::cout << this->data[i*Col + j] << " ";
}
std::cout << '\n';
}
}
int main() {
// our 1 day array of data
double data[6] = { 1,2,3,4,5,6 };
// create and print a MxN matrix - in memory still a 1 day array but represented as 2D array
Matrix<double,2,3> A;
A.fillMatrix( data );
A.printMatrix();
std::cout << '\n';
Matrix<double, 3,2> B( data );
B.printMatrix();
std::cout << '\n';
// Want this in dynamic memory? With shared_ptr the memory is handled for you
// and is cleaned up upon it's destruction. This helps to eliminate memory leaks
// and dangling pointers.
std::shared_ptr<Matrix<float,2,3>> pMatrix( new Matrix<float,2,3>( data ) );
pMatrix->printMatrix();
return 0;
}
Output:
1 2 3
4 5 6
1 2
3 4
5 6
1 2 3
4 5 6

looking for maximum in the array of structs

I'm just a beginner in the learning stage.
I am supposed to arrange a struct of point (x,y,z) so that structure p[n] has the point with the greatest x stored in it. Is my method correct? If not, are there any simper methods to do this?
struct point
{
float x;
float y;
} p[1000];
void sortptx(struct point *t, int ctr);
int main()
{
int n = 100;
sortptx(&p, n);
return 0;
}
void sortptx(struct point *t, int ctr)
{
float temp;
int i;
for(i = 0; i < ctr-1; i++)
{
if (t[ctr]->x < t[i]->x)
{
temp = t[ctr]->x;
t[ctr]->x = t[i]->x;
t[i]->x = temp;
}
}
}
There are at least a few bugs here:
As mentioned in the comments, struct point *t is either a pointer to a single struct point, or an array of points. It is not a pointer to an array of pointers to struct point. So t[i]->x should be t[i].x.
If ctr is intended to be the length of an array of points, t[ctr] will run off the end of the array, and could access uninitialized memory. In that case, t[ctr-1] would be the last element of the array.
Rather than swapping entire points, you are just swapping the x coordinates.
From what I understand you don't want to sort it, but find point with maximum x and make sure it is stored at p[n-1].
struct point
{
float x;
float y;
} p[1000];
This is how it could look like:
void max(struct point *t, int ctr)
{
struct point temp;
int i;
for(i = 0; i < (ctr - 1); i++)
{
if (t[ctr - 1].x < t[i].x)
{
temp = t[ctr - 1];
t[ctr - 1] = t[i];
t[i] = temp;
}
}
}
This function takes struct point *t as an argument, which is pointer to first point just like p is. t[i] is struct point at index i (not pointer to struct point), so you use . instead of -> when you access its members. And since you are indexing from zero, last element of an array of size n has index n-1, which is place where the struct point with the highest x will be stored.
Example:
int main ()
{
for(int i = 0; i < 99; i++)
{
p[i].x = 1;
p[i].y = 3;
}
p[4].x = 7;
int n = 100;
max(p, n);
cout << p[n - 1].x;
return 0;
}
output: 7