Referencing elements from two-dimensional array with a single value - c++

I am probably missing something fundamental, but i cannot find a solution to the following issue.
I have a two-dimensional array of some float elements and i am trying to find a way to be able to reference them by using only a single value.
Example:
float test[5][50];
test[3][25] = 34.67;
cout << test[3][25] << endl;
int id = 25;
cout << *test[id*5+3] << endl;
I am hoping to get same result from both cout. Instead my output looks like this:
34.67
Segmentation fault
What am I doing wrong?
Thanks!

Without testing, I think something like this might work. Note that C++ arrays are major->minor from left dimension to right dimension.
float test[5][50];
test[3][25] = 34.67;
cout << test[3][25] << endl;
int id = 25;
float* test2 = &test[0][0]
cout << test2[(3 * 50) + id] << endl;

test is a float[][] with 5 elements (each of which is a float[] with 50 elements), and you are referring to test[128]. Hence the seg fault.You need to convert from single index to subscript using integer division and mod:
cout << test[id/50][id%50] << endl;
You should assert(id/50<5); to make sure your index is within bounds.

The crash is because you are trying to read the contents of the element as a memory address
*test[id*5+3] means int address = test[id*5+3]; then read memory at address.
If that address is 0 or memory you don't own then it will crash.

Accessing a two-dimensional bitmap (image) with a single reference is often useful.
Use:
int image2D[dim2][dim1];
int *image1D = &image2D[0][0];
Now
image2D[i][j] == image1d[i*dim1+j]

I agree with the first comment, that you really shouldn't do it, but I'll answer anyway.
I think that if you try:
cout << test[id*5+3] << endl;
it should work. There is no need to dereference with *.

Related

Which is correct for sizing a vector

Hi I am just starting to learn cpp and I have two examples of getting the size of a vector in the for statements both seem to work but which is right and why? sizeof(vector) or vector.size()?
Thanks
Brian
void print_vector(vector<string> vector_to_print){
cout << "\nCars vector = ";
for(int i = 0; i < sizeof(vector_to_print); i++){
cout << vector_to_print[i];
(i < vector_to_print.size()-1) ? (cout << ", ") : (cout << endl); // ? the tenrary operator is an if statement (?) do one outcome (:) or the other
}
}
void print_vector(vector <string> vector_to_print){
cout << "\nVector contents = ";
for( int i = 0; i < (vector_to_print.size()); i++ ){
cout << vector_to_print[i];
(i < (vector_to_print.size()-1)) ? (cout << ", ") : (cout << endl);
}
}
Both seem to work I try to rewrite the same code from memory each day for a week to help me learn it and I couldn't quite get the sizeof() to work so I googled it and the example I found used .size() but when I got home and checked what I did yesterday I had used sizeof().
std::vector<std::string> is a container class, which stores an array of std::strings plus other values to assist with manipulation of the array and providing information about the state of the stored array. When you call sizeof(vector_to_print) you are simply getting the size of the container class not the amount of elements in the array that it is storing.
run the following code to prove it to yourself:
std::vector<std::string> vec{"hello","world"};
std::cout << sizeof(vec) << '\n';
vec.push_back("!");
std::cout << sizeof(vec);
the size of the underlying array is changing it goes from 2 elements to 3, but not only does the sizeof(vec) not change, it is always = to 24!
sizeof(vec) must be the same each time (24 bytes on my machine) because sizeof is a compile time constant, because the size of a type must be a compile time constant.
The latter (.size()) is the only valid method
As you already know there are classes in C++. One class can have many methods doing different things and many fields holding different things. When we create an object of class Vector this object has method .size() which as mentioned here returns the number of elements in our object. The complexity is Constant and there is no problem using .size().
When you are using sizeof() as mentioned here on our object you know the size of the object with all its fields (for example vector can have size_t field where it counts all the elements and some field which holds them) you don't need the actual size of the vector in order to iterate the elements this could be wrong in many cases.
P.S. You must use .size()!

c++ pointer and variable address switch of value, why?

I'm trying to modify a variable by a pointer, the problem is that they have the same address but the output is not right.
Here's the code:
int *ret;
int set = 56;
ret = (int *)&ret - 1;
*ret = 3;
cout << ret << endl << &set << endl << set <<endl;
The output is:
0x61ff08
0x61ff08
3
This look great, but what is really weird is that when I replace:
cout << ret << endl << &set << endl << set <<endl;
With this:
cout << ret << endl << set <<endl;
The output becomes:
0x61ff04
56
The pointer change of value and the set variable isn't modified though. It's like if I take out the &set of the cout the address pointed of the pointer exchange his address with the variable.
If I do this:
ret = (int *)&ret + 1; // instead of -1
The output becomes:
0x61ff0c
3
Can I have an explanation? I didn't find any documentation about this.
Can I have an explanation? I didn't find any documentation about this.
Main documentation in this case is C++ standard, though it is sometimes not to easy to find and comprehend information from there. So short version in your case - you can only subtract or add integers to a pointer when resulting pointer would point to an element in the same array or pointing to the fictitious element behind the last (in this case it is illegal to dereference your pointer). For this purpose single variable is treated like one element array (so for pointer to single variable you can basically only do pointer + 1). All other hacky tries to access variables through magic with pointer arithmetics are illegal and lead to Undefined Behavior.
Details about UB you can find here What exactly do "IB" and "UB" mean?
The answer was that the compiler is giving address by he's own way to the variable/pointers according to the code so the addresses can change, to fix this problem by only using addresses
instead of :ret = (int *)&ret - 1;
we can use :ret = (int *)ret - ((int)(ret - &set));
(i didn't want to use the basic ret = &set because i was trying to do it by manipulation only addresses)

c++ creating a static like array with "new" or another way of creating a dynamic array

I know that the common technique of creating a dynamic array using new in C++ is:
int * arr = new int[5];
A book also says:
short tell[10]; // tell is an array of 20 bytes
cout << tell << endl; // displays &tell[0]
cout << &tell << endl; // displays address of the whole array
short (*p)[10] = &tell; // p points to an array of 20 shorts
Now I wonder if there is a way to allocate memory for an array using new, so it can be then assigned to a pointer to the whole array. It might look like this:
int (*p)[5] = new int[5];
The above example doesn't work. The left side looks correct to me. But I don't know what should be on the right.
My intention is to understand if it's possible. And I know that there are std::vector and std::array.
Update:
Here is what I actually wanted to check:
int (*p1)[5] = (int (*)[5]) new int[5];
// size of the whole array
cout << "sizeof(*p1) = " << sizeof(*p1) << endl;
int * p2 = new int[5];
// size of the first element
cout << "sizeof(*p2) = " << sizeof(*p2) << endl;
And here is how to access these arrays:
memset(*p1, 0, sizeof(*p1));
cout << "p1[0] = " << (*p1)[0] << endl;
memset(p2, 0, sizeof(*p2) * 5);
cout << "p2[0] = " << p2[0] << endl;
know that the common technique of creating a dynamic array
In C++ that was written 20 years ago, maybe.
These days you should use std::vector for dynamic arrays and std::array for fixed size array.
If your framework or platform supplies additional array classes (like QT's QVector), they are fine too, as long as you don't mess with C-pointers directly, and you have RAII-based array class.
and as for concrete answer, new T[size] always returns T* , so you cannot catch a pointer returned by new[] with T(*)[size].
The problem is that left and right sights have different types.
The type of:
new int[5]
is
int*.
The type of:
int (*p)[5]
is
int (*)[5].
And compiler cannot assign one to another.
Generally speaking it is impossible to assign T* to T (*)[N]. That is why you need to use the syntax mentioned in the beginning of your question.

OpenCV - wrong results when accessing Mat

Briefly, I would like to sum up values in a Mat matrix. For now I have a 256 by 1 Mat(which is actually a vector, but the Mat format will be important later on). In order to see what happens I'm trying to print it in the loop
`
calcFractile(Mat* in){
cout << "Input = " << *in << endl;
cout << "?!?! ";
for(int k = 0; k<in->rows; k++){
cout << static_cast<int>(in->at<uint8_t>(0,k)) << ", ";
sum += (int)in->at<uint8_t>(0,k);
}
cout <<endl;
}
`
I totally don't understand why, but the cout << "Input[...] line produces correct result, but the loop accessing individual elements fails giving different results
It's not just the value issue, but also positions in the array.
The Mat I'm passing is a histogram of an image, the histogram is single channel, 256 bins.
The problem came from type casting, or rather lack of it.
As soon as I wrote
static_cast(in->at(0,k)
and it worked.
Also just
(int)(in->at(0,k) seems to working fine as well.
Lesson I learned - *always check type casting * not that it's something new, but perhaps someone will benefit

Constants and Pointers

This is going to be a long-winded post, so I apologize in advance.. but trying to ask multiple questions with context:
So, I've been trying to learn C++, and I've been picking everything up fairly easily, but I make a habit of trying to do things alongside the tutorials in "slightly different ways", in order to ensure that I understand the functionality of the thing I'm learning.
I seem to have hit a mental roadblock regarding constants and their involvements with pointers.
In the previous section, I think I got a pretty solid grip on references, dereferences (and the difference between * when used for dereferences and pointers), and then wrote this code:
int a[5];
int * p;
p = a;
cout << "Select the value for the first item at address(" << &a[0] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the second item at address(" << &a[1] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the third item at address(" << &a[2] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the fourth item at address(" << &a[3] << ")" << nl;
cin >> *p;
p++;
cout << "Select the value for the fifth item at address(" << &a[4] << ")" << nl;
cin >> *p;
for (int n=0;n<5;n++)
cout << a[n] << "(" << &a[n] << ")" << nl;
Now, I realize that this isn't necessarily the most "optimized" solution, ever.. but it worked, I was able to "write" into the array I had store on the memory, and display the changes. It was neat, and like I said.. I think I got a pretty good understanding of how these things worked.
..and then, I hit the next section, which used the example:
const char * terry = "hello";
to teach me, and I quote: "As in the case of arrays, the compiler allows the special case that we want to initialize the content at which the pointer points with constants at the same moment the pointer is declared" (this being on the cplusplus.com tutorial).
Anyway, to get to the point: in order to try and familiarize myself with it and the previous section, I tried writing:
const char * p = "Hello.";
for (int n=0;n<5;n++)
cout << p[n] << "(" << &p[n] << ")" << nl;
cout << nl;
..and this does not work. I essentially tried replicating my previous code (although without the writing aspect) in an attempt to be able to read the RAM-location of each character in this constant array, and I experimented with every possible combination of pointers, references, dereferences, etc.. but I just get a print out of the whole "Hello." array with &p.
How in the hell does one get the reference of a constant array? I think I understand the basic premise that I'm creating an array and immediately allocating it to memory, and then assigning a pointer (p) to the first block ("H")'s location.. but I can't seem to print the blocks out. I was able to get the location of the first block to print at one point (can't remember what code I used to do this) and tied it into the for loop, but even then.. it just ALWAYS printed the location of the first block, even when assigned to follow the [n] count.
I have no idea what I'm missing, here, or if I'm just trying to reach "over my head", but maybe I just don't understand the usage/point of creating an array without being able to location the memory assignment of each item within it..
This brings me to my next issue, though. How does one get the memory location of a char variable, whether constant or not? I have been having issues with this code, as well:
char const a = 100;
int * b = &a;
cout << a << nl << *b << nl;
cout << nl;
Obviously, this doesn't work.. because I can't assign b to the location of a, since they're different variables.. and obviously making a char pointer is silly, since it's just going to print messed up/null characters instead of the location (I checked this, obviously.. not just assuming).
I hope I'm just missing an option to use which may just be "more advanced" than where I'm currently at.. but if I'm not, I don't quite see the point in being able to access the block location of any type of variable/constant, if you can't access ALL of them due to restrictions of the type being used.
This problem is sorta what limits the third quoted code, too: the fact that I can't just assign a variable to hold the &p value, since it itself would have to be a char to be compatible.. which is pointless since char can't hold the eight-digit reference.
In
const char * p = "Hello.";
[...] cout << &p[n] [...]
&p[n] is a pointer to char, and cout::operator<< has an overload that takes a pointer to a char and prints a null-terminated string, that's probably why you're confused.