struct Struct_t {
int Value1;
int Value2;
};
vector<Struct_t> Struct;
Struct.resize(10, Struct_t());
for (int i = 0; i < 10; ++i)
{
Struct[i].Value1 = (i + 10) * 3;
Struct[i].Value2 = (i + 5) * 2;
}
How can I create a pointer to Struct[i]?
What I want to do essentially is something like this, but I'm sure this can be done better:
int value = 6;
Struct_t temp = Struct[value], *s;
s = &temp;
s->Value1 = 42;
s->Value2 = 6;
Main goal is, that I can easily create a pointer to Struct[n] with 1 line/function.
So far, the provided answers are missing the elephant in the room. You could create a pointer to a vector element like so:
(Fault-prone) Code Listing
#include <iostream>
#include <vector>
struct Struct_t {
int Value1;
int Value2;
};
int main(void)
{
std::vector<Struct_t> sVec;
sVec.resize(10, Struct_t());
int count = 0;
for (std::vector<Struct_t>::iterator vIt = sVec.begin(); vIt != sVec.end(); ++vIt)
{
vIt->Value1 = (count + 10) * 3;
vIt->Value2 = (count + 5) * 2;
count++;
}
Struct_t* pStruct = &sVec[5];
std::cout << "sVec[5] = (" << pStruct->Value1 << "," << pStruct->Value2
<< ")" << std::endl;
return 0;
}
Sample Output
sVec[5] = (45,20)
However, vector is not an abstract type you want to use if you will be generating pointers to individual elements of the vector/"array". When the vector needs to be re-sized (shrink or grow), the iterators are invalidated, so your pointers will point to now-freed memory, crashing your program. If you want to have raw pointers directly to vector elements, you want to first:
Use a list rather than a vector.
Possibly use managed pointers to handle reference counts.
Finally, when dealing with template classes like vector, list, hash_table, etc, you should try to get used to using the iterator example I used above, as you don't have to worry about checking for exceptions when using an invalid index (the overloaded [] operators can throw exceptions, unless you replace them with the .at() member function instead for element access).
For a std::vector, &v[i], gives you a pointer to the i'th element. Your sample code becomes:
int value = 6;
Struct_t* s = &Struct[value];
s->Value1 = 42;
s->Value2 = 6;
So the one-liner is Struct_t* s = &Struct[value];
There is nothing wrong with doing this, but like most aspects of C++, you need to understand what you are doing. The above code is perfectly valid and guaranteed by the standard. (Also note that the code in this answer avoids an error in the original code where s was a pointer to a temporary copy and no changes were made to the contents of the Struct vector.)
Yes, resizing Struct will invalidate any pointers made before the resize, and yes, using iterators is often a better technique. But this is a correct and reasonable answer to the original question.
Related
I don't understand how I can check if a certain position in an array is been modified or not. Below is an example:
int array[5];
array[2] = 23;
array[4] = 23;
for (int i = 0; i < 5; ++i) {
if (array[i] == ????){
cout << "in array";
} else {
cout << "not in array";
}
}
So I wanted to know how would I get it so the if statement is checking if the item has been modified. So once I becomes 2 it will says it's in array and if not the it should print 'not in array'.
This has to be done using pointers.
This is undefined behavior because array[0] isn't initialized. So when you compare it in your if, what will happen?
You could initialize them all to a value that you consider as "not modified", and check for this value. For instance:
int array[5] = {}; // initializes all elements to the default value for int, which is 0
And then, in your if:
if (array[i] != 0 ) {
If you can't do that because you need the full range of int values, then you can use std::optional instead:
#include <iostream>
#include <optional>
int main() {
std::optional<int> array[5];
array[2] = 23;
array[4] = 0;
for (int i = 0; i < 5; ++i) {
if (array[i]) {
std::cout << "in array" << std::endl;
}
else { std::cout << "not in array" << std::endl; }
}
}
You can't. In C++, it's impossible to determine if an object is uninitialized. Any attempt to read the value of an uninitialized object is Undefined Behavior. They're effectively write-only.
(You might also have a problem with the terminology, or a lack of understanding. array[0] is in the array from the very start, it's just not yet initialized. )
You might use std::map<int, int> values instead. It can truly be empty (values.empty()==true) When you write values[2]=0, a new value is added, and values.size() will be 1 to reflect the new number of elements.
I don't understand how I can check if a certain position in an array is been modified or not.
On x86 you can set a hardware breakpoint on read/write/execute access to a value at a specific address of length of up to 8 bytes. On Linux one API for that is perf_event_open with PERF_TYPE_BREAKPOINT event type. The value of the event counter is how many of interesting accesses to the value at the address have been made.
One option would be using two arrays. A bool array to store the initialization state, and another array to keep desired objects.
(However std::array or std::vector would be better choices than using normal arrays, but that's a different concern)
E.g.
constexpr unsigned int ArrayLen = 5;
bool isInitialized[ArrayLen] = {false};
MyType myArray[ArrayLen]; // In your case `MyType = int`
...
// When setting/resetting update both arrays
void Set(int i, MyType obj)
{
assert(i < ArrayLen);
isInitialized[i] = true;
myArray[i] = std::move(obj);
}
...
// check isInitialized array first before accessing an element
unsigned int targetIndex = 2;
if (isInitialized[targetIndex])
{
auto& obj = myArray[targetIndex];
// use `obj` ...
} else {
// object in `targetIndex` is not initialized
}
In C++17 you can use std::optional so that the initialization state doesn't need to be separately maintained but instead both the state and the object will be bound to a single std::optional object.
I have an array which is not necessarily full.
It can be very sparse.
Is there a good way to iterate through this array without visiting all the possible indexes? (c++ array iterator?)
Or, even if I use array iterator, will it be nothing different from visiting every indexes and checking the value?
Yes, if you use an iterator, it's the same as visiting every index and checking the value, and there's no good way to skip logical holes. You could keep a list of good indices, but if you did that then why not just use a list to store the data in the first place?
If your data is very sparse, perhaps a better data structure would be a std::map, or even an std::unordered_map, depending on your application. These have decent lookup time while not wasting much space, like an array would have to.
Associate Array is what you are trying to build. I suggest you look for a library that does this for you!
If you need a key/value association that simulates an array, just use a std::map holding a std::pair. You can then retrieve your values with the index (key), and iterate quickly over only your set of actual values.
http://en.cppreference.com/w/cpp/container/map
std::map has syntax conveniences like operator[] that will act like an array.
Should you really need to stick with your array based solution boost::filter_iterator could be useful. Here is small example with integer arrays:
#include <algorithm>
#include <iostream>
#include <boost/iterator/filter_iterator.hpp>
struct is_not_null {
bool operator()(int* t) {
return t != NULL ? true : false;
}
};
int main()
{
int* a[] = {NULL, NULL, NULL, NULL, NULL, NULL };
a[0] = new int[3];
a[0][0] = 1; a[0][1] = 2; a[0][2] = 3;
a[3] = new int[3];
a[3][0] = 3; a[3][1] = 4; a[3][2] = 5;
a[5] = new int[3];
a[5][0] = 5; a[5][1] = 6; a[5][2] = 7;
typedef int** base_iterator;
typedef boost::filter_iterator<is_not_null, base_iterator>
FilterIter;
for(FilterIter it = boost::make_filter_iterator< is_not_null >(a, a + 6);
it != boost::make_filter_iterator< is_not_null >(a + 6, a + 6);
++it) {
std::cout << (*it)[0] << " " << (*it)[1] << " " << (*it)[2] << std::endl;
}
// nevermind the leaks
return 0;
}
I'm new to C/C++ and I've been cracking my head but still got no idea how to make an "structure" like this
It's supposed to be a 3D dynamic array using pointers.
I started like this, but got stuck there
int x=5,y=4,z=3;
int ***sec=new int **[x];
It would be enough to know how to make it for a static size of y and z;
Please, I'd appreciate that you help me.
Thanks in advance.
To create dynamically 3D array of integers, it's better you understand 1D and 2D array first.
1D array: You can do this very easily by
const int MAX_SIZE=128;
int *arr1D = new int[MAX_SIZE];
Here, we are creating an int-pointer which will point to a chunk of memory where integers can be stored.
2D array: You may use the solution of above 1D array to create a 2D array. First, create a pointer which should point to a memory block where only other integer pointers are held which ultimately point to actual data. Since our first pointer points to an array of pointers so this will be called as pointer-to-pointer (double pointer).
const int HEIGHT=20;
const int WIDTH=20;
int **arr2D = new int*[WIDTH]; //create an array of int pointers (int*), that will point to
//data as described in 1D array.
for(int i = 0;i < WIDTH; i++){
arr2D[i] = new int[HEIGHT];
}
3D Array: This is what you want to do. Here you may try both the scheme used in above two cases. Apply the same logic as 2D array. Diagram in question explains all. The first array will be pointer-to-pointer-to-pointer (int*** - since it points to double pointers). The solution is as below:
const int X=20;
const int Y=20;
const int z=20;
int ***arr3D = new int**[X];
for(int i =0; i<X; i++){
arr3D[i] = new int*[Y];
for(int j =0; j<Y; j++){
arr3D[i][j] = new int[Z];
for(int k = 0; k<Z;k++){
arr3D[i][j][k] = 0;
}
}
}
// one-liner
typedef std::vector<std::vector<std::vector<int> > > ThreeDimensions;
// expanded
typedef std::vector<int> OneDimension;
typedef std::vector<OneDimension> TwoDimensions;
typedef std::vector<TwoDimension> ThreeDimensions;
(this is tagged c++, after all)
EDIT in response to Joe's question
hello again Joe =) sure. here's the example:
#include <vector>
#include <iostream>
int main(int argc, char* const argv[]) {
/* one-liner */
typedef std::vector<std::vector<std::vector<int> > >ThreeDimensions;
/* expanded */
typedef std::vector<int>OneDimension;
typedef std::vector<OneDimension>TwoDimensions;
typedef std::vector<TwoDimensions>ThreeDimensions;
/*
create 3 * 10 * 25 array filled with '12'
*/
const size_t NElements1(25);
const size_t NElements2(10);
const size_t NElements3(3);
const int InitialValueForAllEntries(12);
ThreeDimensions three_dim(NElements3, TwoDimensions(NElements2, OneDimension(NElements1, InitialValueForAllEntries)));
/* the easiest way to assign a value is to use the subscript operator */
three_dim[0][0][0] = 11;
/* now read the value: */
std::cout << "It should be 11: " << three_dim[0][0][0] << "\n";
/* every other value should be 12: */
std::cout << "It should be 12: " << three_dim[0][1][0] << "\n";
/* get a reference to a 2d vector: */
TwoDimensions& two_dim(three_dim[1]);
/* assignment */
two_dim[2][4] = -1;
/* read it: */
std::cout << "It should be -1: " << two_dim[2][4] << "\n";
/* get a reference to a 1d vector: */
OneDimension& one_dim(two_dim[2]);
/* read it (this is two_dim[2][4], aka three_dim[1][2][4]): */
std::cout << "It should be -1: " << one_dim[4] << "\n";
/* you can also use at(size_t): */
std::cout << "It should be 12: " << one_dim.at(5) << "\n";
return 0;
}
You can try:
for(int i=0;i<x;i++) {
sec[i] = new int *[y];
for(int j=0;j<y;j++) {
sec[i][j] = new int [z];
}
}
And once you are done using this memory you can deallocate it as:
for(int i=0;i<x;i++) {
for(int j=0;j<y;j++) {
delete [] sec[i][j];
}
delete [] sec[i];
}
delete [] sec;
Comprehensive answers.
If you are really writing this in C++ (not rough C) I think you should take another look at this complicated data structure. IMO redesign while keeping in mind what you are trying to do would be better.
What you're trying to do is not idiomatic in C++. Of course, you can use a int***pointer for this, but this is strongly discouraged. In C++ we have better ways to get there.
vector<vector<vector<int> > > foo (5,vector<vector<int> >(4, vector<int>(3)));
This will result in something with the memory layout similar to what you asked for. It supports dynamic resizing and inner vectors to have different sizes just like in your picture. In addition, you don't have to worry about manual allocation / deletion of any of it. Also, the vectors know their size so you don't have to remember it somewhere.
But if you just want a "rectangular" 3D array where all the elements are consecutivly stored in the same memory block, you could use a boost::multiarray.
OK let us take your beginnings
int ***sec = new int**[x];
sec is now an array of int**s of length x, so now I am just going to focus on making the zeroeth element be what you want
sec[0] = new int*[y];
Now sec[0] points to array of int*s of length y, now just need to get the last bit of the tree done, so
sec[0][0] = new int[z];
And finally to get it to the form in your diagram
sec[0][0][z-1] = 0;
This does seem a little like a homework question, make sure you actually understand the answer and why it works.
If it's the actual arrays you'r having problems with look here: Declaring a pointer to multidimensional array and allocating the array
Not sure exactly what you want but you might want to read up on about linked lists.
I have a 3x3 array that I'm trying to create a pointer to and I keep getting this array, what gives?
How do I have to define the pointer? I've tried every combination of [] and *.
Is it possible to do this?
int tempSec[3][3];
int* pTemp = tempSec;
You can do int *pTemp = &tempSec[0][0];
If you want to treat a 3x3 array as an int*, you should probably declare it as an int[9], and use tempSec[3*x+y] instead of tempSec[x][y].
Alternatively, perhaps what you wanted was int (*pTemp)[3] = tempSec? That would then be a pointer to the first element of tempSec, that first element itself being an array.
You can in fact take a pointer to a 2D array:
int (*pTemp)[3][3] = &tempSex;
You'd then use it like this:
(*pTemp)[1][2] = 12;
That's almost certainly not what you want, but in your comment you did ask for it...
Its easyier to use a typedef
typedef int ThreeArray[3];
typedef int ThreeByThree[3][3];
int main(int argc, char* argv[])
{
int data[3][3];
ThreeArray* dPoint = data;
dPoint[0][2] = 5;
dPoint[2][1] = 6;
// Doing it without the typedef makes the syntax very hard to read.
//
int(*xxPointer)[3] = data;
xxPointer[0][1] = 7;
// Building a pointer to a three by Three array directly.
//
ThreeByThree* p1 = &data;
(*p1)[1][2] = 10;
// Building a pointer to a three by Three array directly (without typedef)
//
int(*p2)[3][3] = &data;
(*p2)[1][2] = 11;
// Building a reference to a 3 by 3 array.
//
ThreeByThree& ref1 = data;
ref1[0][0] = 8;
// Building a reference to a 3 by 3 array (Without the typedef)
//
int(&ref2)[3][3] = data;
ref2[1][1] = 9;
return 0;
}
Oh. That's easy!
int aai[3][3];
int* pi = reinterpret_cast<int*>(aai);
You can actually use this awesome technique to cast it into other wonderful types. For example:
int aai[3][3];
int (__stdcall *pfi_lds)(long, double, char*) = reinterpret_cast<int (__stdcall *)(long, double, char*)>(aai);
Isn't that just swell? The question is whether it's meaningful.
You're asking how to lie to your compiler. So the first thing to know is: Why do you want to lie?
int a[20][30];
int* b=&a[0][0];
As Steve pointed out, the proper form is int *pTemp = &tempSec[0][0];. int** pTemp2 = tempSec; does not work. The error given is:
cannot convert 'int (*)[3]' to 'int**' in initialization
It's not stored as an array of pointers to arrays. It's stored as one big vector, and the compiler hides the [a][b] = [a*rowLength+b] from you.
#include <iostream>
using namespace std;
int main()
{
// Allocate on stack and initialize.
int tempSec[3][3];
int n = 0;
for(int x = 0; x < 3; ++x)
for(int y = 0; y < 3; ++y)
tempSec[x][y] = n++;
// Print some addresses.
cout << "Array base: " << size_t(tempSec) << endl;
for(int x = 0; x < 3; ++x)
cout << "Row " << x << " base: " << size_t(tempSec[x]) << endl;
// Print contents.
cout << "As a 1-D vector:" << endl;
int *pTemp = &tempSec[0][0];
for(int k = 0; k < 9; ++k)
cout << "pTemp[" << k << "] = " << pTemp[k] << endl;
return 0;
}
Output:
Array base: 140734799802384
Row 0 base: 140734799802384
Row 1 base: 140734799802396
Row 2 base: 140734799802408
As a 1-D vector:
pTemp[0] = 0
pTemp[1] = 1
pTemp[2] = 2
pTemp[3] = 3
pTemp[4] = 4
pTemp[5] = 5
pTemp[6] = 6
pTemp[7] = 7
pTemp[8] = 8
Note that the Row 0 address is the same as the full array address, and consecutive rows are offset by sizeof(int) * 3 = 12.
Another way to go about doing this, is to first create an array of pointers:
int* pa[3] = { temp[0], temp[1], temp[2] };
Then create a pointer pointer to point to that:
int** pp = pa;
You can then use normal array syntax on that pointer pointer to get the element you're looking for:
int x = pp[1][0]; // gets the first element of the second array
Also, if the only reason you're trying to convert it to a pointer is so you can pass it to a function, you can do this:
void f(int v[3][3]);
As long as the size of the arrays are fixed, you can pass a two-dimensional array to a function like this. It's much more specific than passing a pointer.
Original post follows - please disregard, it is misinformed. Leaving it for posterity's sake ;)
However, here is a link I found regarding memory allocation of 2-dimensional arrays in c++. Perhaps it may be of more value.
Not sure it's what you want, and it's been a while since I've written c++, but the reason your cast fails is because you are going from an array of arrays to a pointer of ints. If, on the other hand, you tried from array to array to a pointer of pointers, it would likely work
int tempSec[3][3];
int** pTemp = tempSec;
remember, your array of arrays is really a contiguous block of memory holding pointers to other contiguous blocks of memory - which is why casting an array of arrays to an array of ints will get you an array of what looks like garbage [that garbage is really memory addresses!].
Again, depends on what you want. If you want it in pointer format, pointer of pointers is the way to go. If you want all 9 elements as one contiguous array, you will have to perform a linearization of your double array.
Let's ask cdecl.org to translate your declaration for us:
int tempSec[3][3]
returns
declare tempSec as array 3 of array 3 of int
Ok, so how do we create a pointer to that? Let's ask cdecl again:
declare pTemp as pointer to array 3 of array 3 of int
returns
int (*pTemp)[3][3]
Since we already have the array 3 of array 3 of int, we can just do:
int (*pTemp)[3][3] = &tempSec;
int tempSec[3][3];
int* pTemp = tempSec[0];
I have to use a dynamic length int array in my program, and want to be able to get the number of objects in it at various points in my code. I am not that familiar with C++, but here is what I have. Why is it not giving me the right length? Thanks.
<#include <iostream>
Using Namespace std;
int length(int*);
void main()
{
int temp[0];
temp[0] = 7;
temp [1] = 10;
temp[2] = '\0';
cout << length(temp) << endl;
}
int length(int* temp)
{
int i = 0;
int count = 0;
while (*temp + i != '\0')
{
count++;
i++;
}
return count;
}
currently it just goes into an endless loop ;_;
In C++ arrays are not dynamic. Your temp array has zero length, and attempting to write to members beyond its length is undefined behaviour. It's most likely not working as it will be writing over some part of the stack.
Either create a fixed size array with enough space to put everything you want to in it, or use a std::vector<int> which is a dynamic data structure.
#include <iostream>
#include <vector>
using namespace std;
int length(int*);
int main () // error: ‘::main’ must return ‘int’
{
int temp[3];
temp[0] = 7;
temp[1] = 10;
// don't use char constants for int values without reason
temp[2] = 0;
cout << length(temp) << endl;
vector<int> vec_temp;
vec_temp.push_back(7);
vec_temp.push_back(10);
cout << vec_temp.size() << endl;
}
int length(int* temp)
{
int i = 0;
int count = 0;
while (*(temp + i) != 0) // *temp + i == (*temp) + i
{
count++;
i++; // don't really need both i and count
}
return count;
}
For the vector, there's no need to specify the size at the start, and you can put a zero in, and finding the length is a simple operation rather than requiring a loop.
Another bug inside your loop was that you were looking at the first member of the array and adding i to that value, rather than incrementing the pointer by i. You don't really need both i and count, so could write that a couple of other ways, either incrementing temp directly:
int length(int* temp)
{
int count = 0;
while (*temp != 0)
{
++count;
++temp;
}
return count;
}
or using count to index temp:
int length(int* temp)
{
int count = 0;
while (temp[count] != 0)
++count;
return count;
}
This approach is a bad idea for a couple of reasons, but first here's some problems:
int temp[0];
This is an array of 0 items, which I don't even think is permitted for stack elements. When declaring an array like this you must specify the maximum number of values you will ever use: E.g. int temp[10];
This is super important! - if you do specify a number less (e.g. [10] and you use [11]) then you will cause a memory overwrite which at best crashes and at worst causes strange bugs that are a nightmare to track down.
The next problem is this line:
while (*temp + i != '\0')
That this line does is take the value stores in the address specified by 'temp' and add i. What you want is to get the value at nth element of the address specified by temp, like so:
while (*(temp + i) != '\0')
So that's what's wrong, but you should take five minutes to think about a better way to do this.
The reasons I mentioned it's a bad idea are:
You need to iterate over the entire array anytime you require its length
You can never store the terminating element (in this case 0) in the array
Instead I would suggest you maintain a separate value that stores the number of elements in the array. A very common way of doing this is to create a class that wraps this concept (a block of elements and the current size).
The C++ standard library comes with a template class named "vector" which can be used for this purpose. It's not quite the same as an array (you must add items first before indexing) but it's very similar. It also provides support for copying/resizing which is handy too.
Here's your program written to use std::vector. Instead of the 'length' function I've added something to print out the values:
#include <vector>
#include <iostream>
void print(std::vector<int> const& vec)
{
using namespace std;
for (size_t i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
cout << endl;
}
int main()
{
std::vector<int> temp;
temp.push_back(7);
temp.push_back(10);
print(temp);
return 0;
}
You could try:
while (*(temp + i) != '\0')
Your current solution is calculating temp[0] + i (equals 7+i), which apparently is not what you want.
Not only C++ arrays are not dynamic as Pete points out, but only strings (char *) terminate with '\0'. (This is not to say that you can't use a similar convention for other types, but it's rather unusual, and for good reasons: in particular, relying on a terminator symbol requires you to loop through an array to find its size!)
In cases like yours it's better to use the standard library.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v;
v.push_back(7);
v.push_back(10);
std::cout << v.size() << std::endl;
return 0;
}
If you don't want to use std::vector, try this:
#include <iostream>
using namespace std;
int main () {
int vet[] = {1,2,3,4,5,6};
cout << (sizeof (vet) / sizeof *(vet)) << endl;
return 0;
}
The most common way to get the size of a fixed-length array is something like this:
int temp[256];
int len = sizeof (temp) / sizeof (temp[0]);
// len == 256 * 4 / 4 == 256 on many platforms.
This doesn't work for dynamic arrays because they're actually pointers.
int* temp = new int[256];
int len = sizeof (temp) / sizeof (temp[0]);
// len == 4 / 4 == 1 on many platforms.
For a dynamic-length array if you care about the size, you're best off storing it somewhere when you allocate the array.
The problem with your loop, as pointed out by many is that you have an operator precedence problem here:
*temp + i
should be:
*(temp + i)
But the bigger problem, also pointed out above, is that you don't appear to understand pointers versus fixed-length arrays and are writing off the end of your array.
If you want to use array properly, you have to allocate enough memory for storing values. Once you specified its length, you can't change it. To know array size, you should store it in variable e.g.:
int n;
cin>>n;
int array = new int[n];
int array_length=n;
If you want to change array's length, best way is to use std container, for example std::vector.
Here is the answer to your question
int myarr [] = {1, 2, 3, 4, 5};
int length = sizeof(myarr) / sizeof(myarr[0]);
cout << length;
Because you only allocate space for an array of zero elements.
The following lines
temp [1] = 10;
temp[2] = '\0';
do not allocate more memory or resize the array. You are simply writing data outside the array, corrupting some other part of the application state. Don't do that. ;)
If you want a resizable array, you can use std::vector (and use the push_back member function to insert new values)
A vector also has the size() member function which tells you the current size.
If you want to use the primitive array, you have to track the size yourself. (and, when resizing the array is necessary, copy all elements from the old array to the new, larger one)
To get dynamic behavior in arrays, use a std::vector, or fall back on the old school c style using int * with manual memory allocation (new and delete)[*]
[*] C implementations (discussed in the context of character arrays as C dynamic string length) used malloc, realloc, and free, but these should be avoided in c++ code.
Try this out:
int length(int* temp)
{
int count = 0;
while (*temp != 0 && *temp != -858993460)
{
++count;
++temp;
}
return count;
}