I have 3 arrays, A[5][3][5], B[5][4][5], C[5][2][5].
Is it possible to access them by an array of pointers, with their second dimension being different? Something like:
int A[5][3][5], B[5][4][5], C[5][2][5];
int ***D[3];
D[0] = A;
D[1] = B;
D[2] = C;
I know this is wrong, I just want to know if it's possible to access them by one array?
No, if the second dimension is different it won't work. The best you can do is something like this:
struct arr {
int *p; // pointer to first element
int x, y, z; // array size
int &at(int i, int j, int k) {
return p[((i*y)+j)*z+k];
}
}
Or you can use your favorite multidimensional array library. C++ lacks built-in support for multidimensional arrays unless all but the first size is known at compile time, and C99 VLAs won't work in this situation. This is because C/C++ use the type of the array to figure out how big it is in each dimension (except the first dimension, which can be unspecified).
It's definitely not possible to do what you want directly due to the type system's restrictions, but you may want to consider something like the following (in C++11 syntax):
#include <vector>
#include <array>
#include <iostream>
template <typename T, size_t x, size_t z>
struct Ragged : std::array<std::vector<std::array<T, z>>, x> {
Ragged(size_t y) {
for (auto &i : *this) {
i.resize(y);
}
}
};
int main() {
using R5y5 = Ragged<int, 5, 5>;
R5y5 a(3), b(4), c(2);
vector<R5y5> d{a, b, c};
d[1][1][2][3] = 99; // checked at() calls supported for all dimensions, too
for (auto const &d : D) {
for (auto const &x : d) {
std::cout << "[";
for (auto const &y : x) {
std::cout << "[";
for (auto const &z : y) {
std::cout << z << " ";
}
std::cout << "]";
}
std::cout << "]" << std::endl;
}
std::cout << std::endl;
}
}
This gets you multidimensional operator[] access to d and its elements, and allows you to put whatever y-dimensioned array inside d you want to. Note that the 3-dimensional pseudo-arrays are no longer stored completely compactly, but in potentially growable 2-D slices.
#include <stdio.h>
int main(){
int A[5][3][5], B[5][4][5], C[5][2][5];
void *D[3];
D[0]=&A;
D[1]=&B;
D[2]=&C;
B[1][2][3] = 99;
printf("%d\n", (*(int(*)[5][4][5])D[1])[1][2][3]);//99
return 0;
}
Related
I can't able to understand , so please help me .
Whrn we are passing the array to any function and then we write the array type in function parameter to fetch it but why we are not initialize its size in the parameter .
Of course you could specify (fixed) size of array as function parameter - you have to pass array by reference.
void func(int (&x)[100]);
is passing array of int with size 100.
You could even make a template for it
template<class T, size_t N> void func(T (&x)[N]) {...}
In C++, always prefer containers to raw pointers or arrays when possible.
Array types in function signatures are actually pointers. The following three declarations are all exactly the same:
void foo(int a[10]);
void foo(int a[]);
void foo(int* a);
In all three cases, foo takes a single parameter: a pointer to an int. When you pass an array to that function, it implicitly decays to a pointer to its first element.
When an array decays into a pointer, the length of the array is lost. That means the following code will compile, but is logically wrong:
void foo(int a[10]) {
for (size_t i = 0; i < 10; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
// Whoops, wrong size array!
int arr[5] = {};
foo(arr);
}
Live Demo
The length declaration, in this case, is a complete and total lie. Writing a meaningless number in the function definition just increases the risk someone will make an error.
If you must use raw pointers for a function parameter accepting an array, your function should also accept a size parameter:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
foo(arr, 5);
}
Live Demo
This is also dangerous though, since it's entirely possible for someone to pass the wrong size and cause errors:
void foo(int* a, size_t length) {
for (size_t i = 0; i < length; ++i) {
std::cout << a[i] << '\n';
}
}
int main() {
int arr[5] = {};
//Whoops, passed the wrong size!
foo(arr, 10);
}
Live Demo
For that reason, you should prefer to use a container:
void foo(const std::vector<int>& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
}
Live Demo
If you don't know what type of container to use; default to std::vector. If your function must support multiple types of containers, use a template:
template <typename Container>
void foo(const Container& a) {
for (int i : a) {
std::cout << i << '\n';
}
}
int main() {
std::vector<int> arr(5);
foo(arr);
std::array<int, 5> arr2 = {};
foo(arr2);
}
Live Demo
I have a struct Foo;
typedef struct {
int bar;
char baz;
} Foo;
Suppose I then declare an array of Foo as;
Foo* arr = new Foo[300];
And proceed to initialize every member with a loop. I would like very much to be able to get an array of all members bar;
int* barr_arr = ...
What is the most efficient way to do this? Is there some way to exploit the memory layout such that I need not loop over the entire Foo array?
Since we know the memory layout in advance could we exploit the fact that we know the address of every member if we're clever about alignment?
What is the most efficient way to do this? Is there some way to exploit the memory layout such that I need not loop over the entire Foo array?
I don't think there is away to do that without looping. You can simplify your code by using std::transform but std::transform does loop.
Also, I would recommend using std::vector instead of allocating an array using new.
std::vector<Foo> arr(300);
....
std::vector<int> bArr(arr.size());
std::transform(arr.begin(), arr.end(), bArr.begin(), [] -> (Foo const& f) { return f.bar; });
When you are initializing the first array, you can grab a pointer to the field inside each element and store that in a separate array.
struct Foo
{
int bar;
float baz;
};
const int SIZE = 5;
Foo foos[SIZE];
int *bars[SIZE];
for(int c = 0; c < SIZE; c++) {
foos[c].bar = c;
foos[c].baz = c;
bars[c] = &foos[c].bar; // Grab pointer to field
}
for(int c = 0; c < SIZE; c++) {
std::cout << "Bar Value: " << *bars[c] << std::endl;
}
If Foos typically exist in arrays, and corresponding arrays of bars and bazs often need to be accessed, I would suggest redesigning your data structures to better suit your problem. Obviously, we're not reading the code that inspired this question, but given the information provided, I might suggest something like:
struct FooArray {
int* bars;
char* bazes;
size_t n_elements;
};
This removes the need to allocate a new buffer for the bar array, which, depending on how many Foos are being processed, might entail significant memory savings.
I would also note that, if you're not working at a low level and don't actually need an int* but can do with a std::vector<int>, then #R Sahu's answer is likely a more appropriate solution.
The goal drives the design.
If your main use is to pass all bar members in a row, same for baz members, then create separate containers:
std::vector<int> bar;
std::vector<char> baz;
Then passing bar as an array is straightforward: just use bar.data().
If you add a constructor to your Foo that takes the size of array, you could have only one object of Foo. You can then make it that you can access either the whole vector data or individual elements with subscript:
#include <iostream>
#include <vector>
#include <memory>
struct Foo
{
std::vector<int> bars;
std::vector<char> bazs;
std::size_t size;
Foo(size_t size, int bar = 0, char baz = 0) :
bars(size, bar), bazs(size, baz), size{size}
{
}
auto operator[](size_t n)
{
// if (n >= size) ...
struct
{
int &bar;
char &baz;
} temp{ bars[n], bazs[n] };
return temp;
}
};
int main()
{
Foo arr(30, 100, 'a'); // 30 items
std::cout << arr[29].bar << std::endl;
std::cout << arr[29].baz << std::endl;
std::cout << arr.bars[29] << std::endl;
std::cout << arr.bazs[29] << std::endl;
std::unique_ptr<Foo> arr2 = std::make_unique<Foo>(25, 10, 'b'); // 25 items
std::cout << arr2->operator[](15).bar << std::endl;
std::cout << arr2->operator[](15).baz << std::endl;
arr2->bars[15] = 11;
std::cout << arr2->bars[15] << std::endl;
arr2->bazs[15] = 'c';
std::cout << arr2->bazs[15] << std::endl;
return 0;
}
Demo: https://ideone.com/TiVwOT
100
a
100
a
10
b
11
c
I have this struct:
struct noduri {
int nod[100];
};
and this function:
int clearMatrix(int var)
{
cout << all[1].nod[30];
}
int main()
{
noduri all[100];
cout << all[1].nod[30];
return 0;
}
and I want the struct to be assigned to all 100 elements of array all[], when I do cout << all[1].nod[30]; everything works fine, no errors, it outputs 0. When I call clearMatrix(1) I get this error : error: request for member nod in all[1], which is of non-class type int, what am I doing wrong ?!
The array variable all is local to the main function, so you cannot reference it in clearMatrix unless you pass a pointer to it into the function:
int clearMatrix(int var, noduri *all)
{
cout<<all[1].nod[30];
}
int main()
{
noduri all[100];
clearMatrix(5, all);
return 0;
}
you are reffering in the function that array which is not in its scope, you need to do it as
int clearMatrix(int var,noduri *all)
{
cout<<all[1].nod[30]; // as here you have the base address of the array of type noduri you can refer it.
}
int main()
{
noduri all[100];
clearMatrix(5, all);
return 0;
}
You are using raw arrays. That's not a good idea. Use std::vector if the size if not known at compile time, consider std::array if it is known at compile time and dynamic resizing would cause measurable performance problems.
One of the problems with raw arrays in C++ is that it's not at all(!) as easy to pass them to a function like, say, an int or a double. std::vector and std::array, in contrast, are as easy to pass to a function like any other normal type.
Here's a complete example:
#include <array>
#include <iostream>
struct noduri {
std::array<int, 100> nod;
};
void clearMatrix(std::array<noduri, 100> const &array) {
std::cout << array[1].nod[30];
}
int main() {
std::array<noduri, 100> all;
std::cout << all[1].nod[30];
}
Note that std::array is only available if your compiler supports C++11. For an older compiler, use boost::array or just do it with a std::vector.
The code you showed will not be compiled and has no any sense. If I have understood correctly you want to assign each element of the array by some value in function clearMatrix. If so then the code will look the following way
#include <iostream>
struct noduri
{
int nod[100];
};
int clearMatrix( noduri *matrix, int size, int var )
{
for ( int i = 0; i < size; i++ )
{
for ( int &n : matrix[i].nod ) n = var;
}
}
int main()
{
const int N = 100;
noduri all[N] = {};
std::cout << all[1].nod[30] << std::endl;
clearMatrix( all, N, 10 );
std::cout << all[1].nod[30] << std::endl;
return 0;
}
This is the working program to pass an array in a function, but I am not able to understand that in the print function only the base address of the array is passed but still I am able to access the array with subscript a[i]. I know the correct method will be *(a+i) but why does it work with the subscript too?
#include <iostream>
#include <conio.h>
void print(int *a);
using namespace std;
int main()
{
int arr[3]={1,2,3};
print(arr);
getch();
return 0;
}
void print(int *a)
{
for(int i=0;i<3;i++)
{
cout<<a[i];//how we are able to access array with subscipt a[i]
}
}
Since you are passing a pointer (pointing to a specific memory address) you can treat it as usual even inside the function. Pointers and arrays are very closely related and the use is just fine.
a[0] and *a are the same thing, so are a[1] and *(a+1) etc.
"A pointer is equivalent to the address of the first element that it points to" - from http://www.cplusplus.com/doc/tutorial/pointers/
The array can be passed like that, but the other way is to put name of the array followed by empty []:
#include <iostream>
#include <conio.h>
void print(int *a);
using namespace std;
int main()
{
int arr[3]={1,2,3};
print(arr);
getch();
return 0;
}
void print(int a[])
{
for(int i=0;i<3;i++)
{
cout<<a[i];//how we are able to access array with subscipt a[i]
}
}
both methods pass the address of the first number in array, so both methods work.
//how we are able to access array with subscipt a[i]
a[i] is the same thing as *(a + i).
As it is now, your print will only work for arrays of the exact size 3, so:
If the array happens to have more than 3 elements, some elements will not be printed.
If it happens to have less than 3, you'll access whatever is in memory behind the array, which is undefined behavior (translation: very bad!).
The size of the array gets "forgotten" when you pass the array to a function, so either explicitly pass the size to make the function reusable for arrays of all sizes (reusability is the point of having functions after all!)...
void print(int const* a, size_t a_size) {
for (size_t i = 0; i < a_size; ++i) // size_t is the appropriate type here, not int.
std::cout << a[i] << std::endl; // Use std::endl to be able to discern where teh current number ends and the next starts!
}
// ...
int arr[3] = {1, 2, 3};
const size_t arr_size = sizeof(arr) / sizeof(arr[0]);
print(arr, arr_size);
...or do it in the C++ way and use std::vector...
void print(const std::vector<int>& a) {
for (const auto& s : a) // The new C++11 "for each" syntax.
std::cout << s << std::endl;
}
// ...
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
print(a);
...or even make it generic...
template <typename T>
void print(const std::vector<T>& a) {
for (const auto& s : a)
std::cout << s << std::endl;
}
Example code:
#include <cstdlib>
#include <iostream>
using namespace std;
class A {
public:
A(int x, int y) : x(x), y(y) {}
int x, y;
};
class B {
public:
operator A() {
return A(x,y);
}
float x, y;
};
void func1(A a) {
cout << "(" << a.x << "," << a.y << ")" << endl;
}
void func2(A *a, int len) {
for(int i=0; i<len; ++i) {
cout << "(" << a->x << "," << a->y << ")";
}
cout << endl;
}
int main(int argc, char** argv) {
B b[10];
func1(b[0]);
//func2(b, 10);
return(EXIT_SUCCESS);
}
func1 works as expected, but func2 throws a compile-time error. Is there anything I can add to class B to make this work? I suspect not, but it doesn't hurt to ask, right?
I assume it won't work because the size of A is different from the size of B?
void func2(A *a, int len)
When you try to pass a pointer of type B to func2 there is no acceptable conversion from B* to A*. These are two different types from A and B, though the type B has a conversion operator to type A.
When you pass array to a method you are only passing the address of the first element not the actual copy of the array nor the first element.
In func1 you pass first element of array which is object of class B. Because B has operator A() it can convert B to A and new object of class A is passed to func1
In func2 you pass pointer to an array of B objects which is not the same as array of A objects so you get error.
To solve it you could have a transformation method that takes pointer to array of B's and iterators over it and for each calls func1 or something like that.
The other answers have addressed the core issue. But for completeness, it's worth noting that
I assume it won't work because the
size of A is different from the size
of B?
is incorrect.
First, A and B as given in this example would actually be the same size on many current compilers.
But even when A and B are the same size, the compiler will not perform this kind of conversion automatically. In fact, even if they have the exact same memory layout of member variables, the compiler will still not do it.