I'm using a convolution process using a 3x3 grid over a 2d image that is represented in a 1d array. I am iterating over certain pixels and need access to the surrounding pixels (ignoring edge cases). Is it possible to have a pointer that always points to a location next to another pointer?
int* a = new int[5];
//populate with data (0, 2, 4, 6, 8)
int* b = &a[2]; //4
int* c = b+1; //6
b++; //b->6, c->6
//What if after b++ I want c->8?
Is there any way to make a pointer relative to another pointer such that when the main pointer is changed, the other pointers change with it? So, a pointer that always points to the neighbor of another pointer.
Incrementing b does not change c. If you want both pointers to move in parallel, you must increment both of them:
b++;
c++;
This seems like more trouble than it's worth, though, since you can just do b + 1 to find the "next" element in the array.
Related
I have the following function ( I want to print all elements from a given row)
void print_row(int j, int row_dimension, int *p)
{
p = p + (j * row_dimension);
for(int i = 0; i< row_dimension; i++)
cout<<*(p+i)<< " ";
}
Creating an array
int j[3][3]={{1,2,3},
{4,5,6},
{7,8,9} };
What I do not understand is why can I call the function in the following way :
print_row(i, 3, *j);
Why can I give as a parameter "*j" ? Shouldn't an address be passed? Why can I use the indirection operator?
int j[3][3] =
{{1,2,3},
{4,5,6},
{7,8,9}}; // 2d array
auto t1 = j; // int (*t1)[3]
auto t2 = *j; // int *t2
So what is happening is that *j produces j[0], which is an int[3] which then decays to an int*.
j is in fact an array of arrays. As such, *j is an array of three integers, and when used as a rvalue, it decays to a pointer to its first element, said differently, it decays to &j[0][0].
Then in printrow you compute the starting address of the first element of each subarray - that's the less nice part, I'll come back later to it. Then you correctly use the *(p+i) equivalent of p[i] to access each element of the subarray.
The remaining part of the answer is my interpretation of a strict reading of C standard
I said that computing the starting address of each subarray was the less nice part. It works because we all know that a 2D array of size NxM has the same representation in memory as a linear array of size N*M and we alias those representations. But if we respect strictly the standard, as an int pointer, &p[i][j] points to the first element of an array of three elements. As such, when you add the size of a row, you point past the end of the array which leads to undefined behaviour if you later dereference this address. Of course it works with all common compilers, but on an old question of mine, #HansPassant gave me a reference on experimental compilers able to enforce controls on arrays sizes. Those compilers could detect the access past the end of the array and raise a run time error... but it would break a lot of existing code!
To be strictly standard conformant, you should use a pointer to arrays of 3 integers. It requires the use of Variable Length Arrays, which is an optional feature but is fully standard conformant for system supporting it. Alternatively, you can go down to the byte representation of the 2D array, get its initial address, and from there compute as byte addresses the starting point of each subarray. It is a lot of boiling plate address computations but it fully respect the ##!%$ strict aliasing rule...
TL/DR: this code works with all common compilers, and will probably work with a lot of future versions of them, but it is not correct in a strict interpretation of the standard.
Your code works because *j is a pointer which has the same value as j or j[0]. Such behavior caused by mechanics of how two-dimensional arrays are handled by the compiler.
When you declare 2D array:
int j[3][3]={{1,2,3},
{4,5,6},
{7,8,9}};
compiler actually puts all values sequentially in memory, so the following declaration will have the same footprint:
int j[9]={1,2,3,4,5,6,7,8,9};
So in your case pointers j, *j and j[0] just point to the same place in memory.
Memory isn't multidimensional, so even if its a 2D array, it's data will be placed in a sequential manner, so if you get a pointer to that array -- that is implicitly a pointer to the first element of it -- and start reading the elements sequentially, you will iterate through all elements of this 2D array, reading element from the subsequent rows just after the last element of the previous one.
I'm new to using C++ for complicated programming. I've been sifting through some leftover, uncommented, academic code handed down through my department, and I've stumbled across something I have no real idea how to google for. I don't understand the syntax in referencing an array of structs.
Here is a trimmed version of what I'm struggling with:
typedef struct
{
double x0,y0;
double r;
} circle;
double foo()
{
int N = 3;
double mtt;
circle circles[N];
for (int i = 0; i < N; i++)
{
mtt += mtt_call_func((circles+i), N);
}
return mtt;
}
What does (circles+i) mean in this case?
EDIT: the function should have (circles + i), not (circle + i).
circles+i is equivalent to &circles[i]. That's how pointer arithmetic works in C++.
Why is there a pointer? Well, when you give the name of an array, in a context other than &circles or sizeof circles, a temporary pointer is created that points to the first member of the array; that's what your code works with. Arrays are second-class citizens in C++; they don't behave like objects.
(I'm assuming your circle+i was a typo for circles+i as the others suggested)
circle+i means "take a pointer circle and move it i times by the size of the object pointed to by it". Pointer is involved because the name of the array is a pointer to it's first element.
Apart from this you should initialize an integer counter variable that is used in loop:
for (int i = 0; i < N; i++)
^^^^
{
mtt += mtt_call_func( ( circles + i), N);
^ // typo
}
In C, as in C++, it is legal to treat an array as a pointer. So circles+i adds i times the size of circle to the address of circles.
It might be clearer to write &circles[i]; in this form, it is more obvious that the expression produces a pointer to the ith struct in the array.
Each vector you declare in stack it's actually a pointer to the first index, 0, of the vector. Using i you move from index to index. As result, (circles+i) it's the equivalent of &circles[i].
& means the address of the variable. As in your function call, you send a pointer which stores an address of a variable, therefore & is required in front of circles[i] if you were to change to that, as you need the address of the i index of the vector circles to run your function.
For more about pointers, vectors and structures check this out: http://pw1.netcom.com/~tjensen/ptr/pointers.htm
It should cover you through ground basics.
If I declare a 2D array
int A[sz][sz];
How can I create a pointer to this object?
I ask because I want to return an array via pointer to a pointer, int**, from a function but I want to build the array without knowing the size beforehand. The size will be passed as an argument. I want to know if there is a way to do this without using dynamic allocation.
The problem is if I do something like int** A inside the function this gives A no information about the size I want.
How can I create the array and then assign a pointer to this array, if it's a 2D array.
I should be more clear. I want return a pointer to a pointer so it wouldn't be a pointer to the 2D array but a something like int**.
Your problem is, that a 2D array in the form int** requires an array of int* for the two step dereferencing, which simply does not exist when you declare an array with int A[sz][sz];.
You can build it yourself like this:
int* pointers[sz];
for(size_t i = sz; i--; ) pointers[i] = A[i];
This might seem absurd, but is rooted in the way C handles arrays: A[i] is of type int ()[sz], which is the subarray of row i. But when you use that array in the assignment, it decays to a pointer to the first element in that subarray, which is of type int*. After the loop, A and pointers are two very different things (the type of A is int ()[sz][sz])
Sidenote: You say that you want to return this from a function. If your array is allocated on the stack, you must not return a pointer to its data, it will disappear the moment your function returns. You can only return pointers/references to objects that have either static storage or are part of another existing object. If you fail to comply with this, you are likely to get stack corruption.
Edit:
A little known fact about C is, that you can actually pass around pointers to real C arrays, not just the pointer types that an array decays to. Here is a small program to demonstrate this:
#include <stddef.h>
#include <stdio.h>
int (*foo(int size, int (*bar)[size][size], int y))[] {
return &(*bar)[y];
}
int main() {
int mySize = 30;
int baz[mySize][mySize];
int (*result)[mySize];
result = foo(mySize, &baz, 15);
printf("%ld\n", (size_t)result - (size_t)baz);
}
The expected output of this example program is 1800. The important thing is that the actual size of the array must be known, either by being a compile time constant, or by being passed along with the array pointer (and if it's passed along with the array pointer, the size argument must appear before the array pointer does).
Let me flesh out your question a little bit. You mention:
I ask because I want to return an array [...] from a function but I
want to build the array without knowing the size beforehand. The size
will be passed as an argument. I want to know if there is a way to do
this without using dynamic allocation.
For the I want to return an array from a function [...] size passed as an argument, it seems reasonable to me that you can use std::vector everywhere, and call its .data() method when you need access to the underlying array (which is guaranteed to be contiguous). For example:
std:vector<double> myfun(size_t N) {
std::vector<double> r(N);
// fill r[0], r[1], ..., r[N-1]
return r;
}
// later on:
r.data(); // gives you a pointer to the underlying double[N]
And for the I want to to do this without dynamic allocation, that is not possible unless you know the size at compile time. If that is the case, then do exactly as before but use std::array, which can implement optimizations based on known compile-time size:
std::array<double, N> myfun() {
std::array<double, N> r;
// fill r[0], r[1], ..., r[N-1]
return r;
}
// later on:
r.data(); // gives you a pointer to the underlying double[N]
And to be generic, I would actually use a template function capable of working with arbitrary containers:
template<typename T>
void myfun(T& data) {
for(int k=0; k<data.size(); k++) {
// do stuff to data[k]
}
}
// call as, for example:
std::vector<double> data(10);
myfun(data);
// or equally valid:
std::array<double, 10> data;
myfun(data);
Finally, if you are working with two-dimensional data, please remember that when you store the Matrix in row-major order that is:
Matrix [1, 2; 3 4] is stored as [1 2 3 4]
then you can refer to element (i, j) of the matrix by calling data[i * ncols + j]. For example: consider a three by four matrix:
a b c d
e f g h
i j k l
The element (2, 2) (that is: third row, third column because we assume zero-based C-type indexing) is calculated as: M[2][2] = M[2 * 4 + 2] = M[10] = k. This is the case because it was stored as:
[a b c d e f g h i j k l]
[0 1 2 3 4 5 6 7 8 9 10 11]
and k is the element with index 10.
the responses to your question are weird. Just do this:
int A[2][2];
int**p =NULL;
*p = A[0]; // **p==A[0][0] , *(*p+1)==A[0][1]
If I have a pointer that is pointing to an element in a vector, say element 2, and then that element gets swapped with element 4 of the same vector. Is the pointer now pointing to element 2, element 4, or neither? Example:
vector a is equal to [1,2,3,4,5]
create pointer that points to the element 2, which is equal to 3 in this case
swap elements 2 and 4
vector a is now [1,2,5,4,3]
where is the vector pointing to?
You mean, "where is the pointer pointing to?". If that's the case, it'll point to the same location in memory as before which is now occupied by the value 5.
Also, by swapping I assume you meant swapping the values between two locations.
Why?
Simply because your pointer points to a memory location. What's stored there doesn't matter --- it could be a value, or it could be garbage. When you dereference it (to see what the value is) it will return the value stored at that location.
Since you've swapped the values, the value at that location is 5 not 3 hence, the pointer is still pointing to the same location and is unchanged but the value at the location has changed.
Sample Code:
// Create the vector
int a[] = {1,2,3,4,5};
int* ptr = &a[2];
// Display original status
std::cout<<"Original Value: "<<*ptr<<std::endl;
std::cout<<"Address: "<<ptr<<std::endl;
// Swap values
std::swap(a[2],a[4]);
// Check
std::cout<<"New Value: "<<*ptr<<std::endl;
std::cout<<"Address: "<<ptr<<std::endl;
Note:
I've used an array of integers in the example but if by vector you meant std::vector, the same will hold assuming no reallocation has taken place (check out this SO answer).
Assume I have an array a and an array b. Both have the same type and size but different values.
Now I create 3 or so pointers that point to different elements in a, you could say a[0], a[4] and a[13].
Now if I overwrite a with b via a=b - Where will the pointers point?
Do the pointers still point to their original positions in a but the values they point to are now those of b?
Arrays are not assignable in C++. Once you declare an array:
int a[10];
there is no way of overwriting it, only of changing the values it contains. Specifically, you can't do:
int a[10], b[10];
a = b; // cannot work in C++ (or C)
If you create the array dynamically and assign pointers:
int * a = new int[10];
int * p = a + 1;
int * b = new int[10];
a = b;
then the pointer p still points into the first array, but you have a memory leak.
In the case of a struct containing an array:
struct S {
int a[10];
};
S s1, s2;
int * p = s1.a + 1;
s1 = s2;
then the pointer p still points into the first struct's array, but the array contents will have been overwritten with the array contents from the second struct.
That's an interesting question. So lets break it down:
Where will the pointers point?
Same place as they did before. They only contain the address of the memory, nothing more. Changing "a" will not change the pointers.
Will the pointers point to their original positions in a but the values they point to are now those of b?
If a was created as
int *a = new int[34];
then no.
If you don't directly change the variables that are storing your pointers, nothing is going to change the location they point to. Changing the values stored in the "pointed to" locations will change the dereferenced values of your pointers, but they still point to the same place.
Learning how to use a good graphical debugger and stepping through a test program would help illustrate what is going on. I don't know if you are on the windows platform, but the visual studio (and I would think Visual C++ Express) debugger will show you everything you need to know so you can run your own experiment and see exactly what your code is doing.
You can not overwrite anything with a=b. Effectively this will leak memory, by leaving your whole 'a' array somewhere into the memory with no pointer to it. 'a' will point to the first element of 'b' after a=b.
After a declaration like int * a = new a[5]; , your 'a' point to the first element of the array. You can do pointer arithmetic like a++, which will then go to the second element in the array, leaving your first element with no pointer to it. The same way a=b will point it to the first element of the b array.
Your other pointers a[3], a[14] e.t.c. will still point to the same memory as before.
Note that a[0] is the same as 'a'.
You must make a difference between arrays and pointers. If you use arrays you cannot make a=b.
If you use pointers you can make a = b and that will mean that a points where b points. The values inside them will not change, but it will be impossible to access. Once you make a = b, when accessing a[3] you will access b[3], because a[3] means: "where a points + 3", and a points where b points, hence b[3].
If you don't free where a was allocated, that info is still in memory, so if you made 3 pointers that point where a used to point + some value, that info is still accessible and not modified.
a=b won't work, but you can copy array b into a using STL.
As an example :
int a[15] = {0};
int b[15] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
int *p1 = a; // pointer to a[0]
int *p2 = a+4; // pointer to a[4]
int *p3 = a+13; // pointer to a[13]
std::copy(&b[0], &b[15], a);
If you have pointers to array a elements declared before the copy :
pointers' address won't change if you copy b into a
only pointers' values
change