Returning a pointer to an array C++ - c++

I have a function that needs to return a pointer to an array:
int * count()
{
static int myInt[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
return &myInt[10];
}
inside my main function I want to display one of the ints from that array, like here at index 3
int main(int argc, const char * argv[])
{
int myInt2[10] = *count();
std::cout << myInt2[3] << "\n\n";
return 0;
}
this however gives me the error: "Array initializer must be an initializer list"
how do I create an array within my main function that uses the pointer to get the same elements as the array at the pointer?

A few problems in your code:
1) you need to return a pointer to the beginning of the array in count:
return &myInt[0];
or
return myInt; //should suffice.
Then when you initialize myInt2:
int* myInt2 = count();
You can also copy one array into the other:
int myInt2[10];
std::copy(count(), count()+10, myInt2);
Note copying will create a second array using separate memory than the first.

You don't need pointers, references are fine.
int (&count())[10]
{
static int myInt[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
return myInt;
}
int main(int argc, const char * argv[])
{
int (&myInt2)[10] = count();
std::cout << myInt2[3] << "\n\n";
return 0;
}

Related

how to print an n-dimensional array in c++

I would like to write a function that can print different arrays. For instance:
#include<iostream>
using namespace std;
int main(){
int a[10];
int b[3][2];
for(int i = 0; i < 10; i++){
a[i] = i;
}
for(int i = 0; i < 3; i++){
for(int j = 0; j < 2; j++){
b[i][j] = i * 2 + j;
}
}
print_arr(a, /*some input*/);
// output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
print_arr(b, /*some input*/);
// output:
// 0, 1
// 2, 3
// 4, 5
return 0;
}
can somebody help me or say that this is impossible.
maybe this question is already answered. In that case please can you share the link of that question
You could create a function template that unwraps the array recursively.
Example:
#include <iostream>
#include <type_traits>
// only enable the function for arrays
template<class T, std::enable_if_t<std::is_array_v<T>, int> = 0>
void print_arr(const T& x) {
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1) // more dimensions to go
print_arr(in); // call to unwrap next dimension
else
std::cout << in << ' '; // last dimension, print the value
}
std::cout << '\n';
}
Demo
Since the name print_arr suggests that you will not need SFINAE you could also replace the enable_if_t part of the template with a static_assert inside the function:
template<class T>
void print_arr(const T& x) {
static_assert(std::is_array_v<T>);
// ...
Instead of streaming directly to std::cout, you could add a std::ostream& parameter to make it stream to any stream
template<class T>
void print_arr(std::ostream& os, const T& x) {
static_assert(std::is_array_v<T>);
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1)
print_arr(os, in);
else
os << in << ' ';
}
os << '\n';
}
// ...
print_arr(std::cout, a);
print_arr(std::cout, b);
Or you could make it return a std::string of the complete output which lets you do what you want with it afterwards.
Example:
#include <sstream>
template<class T>
std::string print_arr(const T& x) {
static_assert(std::is_array_v<T>);
std::ostringstream os;
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1)
os << print_arr(in);
else
os << in << ' ';
}
os << '\n';
return os.str();
}
// ...
std::cout << print_arr(a);
std::cout << print_arr(b);
Ted Lyngmo's answer is definitely the most concise, and probably the closest to achieving what you asked for, but there's still a few things worth pointing out including an alternate solution that might make sense in some circumstances.
First of all, it's important for anyone reading this to understand that C and C++ types don't include any kind of runtime type information by default. Yes it's true, RTTI exists for record types, but a built-in C array like int arr[2][3] is not much more than a bit of sugar to say "give me a region of memory large enough to store 6 ints". This is in contrast for example to a language like python, where a list object will include metadata about the size and contents. It's this metadata that allows you to write very flexible functions than can query the object itself about its structure, and of course it comes at a cost.
When we introduce a templated solution like the one above, we haven't added runtime type information, we've asked the compiler to generate code for every possible permutation of array type that we might need. This is fine if you only have a couple of them, but if the function gets used a lot, with many different array types, things grow really fast. This could actually become a problem in some environments. Consider for example the following main function:
int main(int argc, char **argv)
{
int arr1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
print_arr(arr1);
int arr2[3] = {13, 14, 15};
print_arr(arr2);
int arr3[3][2][2] = {{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}};
print_arr(arr3);
return 0;
}
And now look at the AST that gets generated:
jon#prompt$ clang++ -fsyntax-only -Xclang -ast-dump test.cpp -std=c++17 | grep FunctionDecl | grep print_arr
| |-FunctionDecl 0x10921fd88 <line:6:1, line:15:1> line:6:6 print_arr 'void (const T &)'
| |-FunctionDecl 0x109224c18 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3][4])'
| |-FunctionDecl 0x109225ab8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3])'
| |-FunctionDecl 0x1092270a8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3][2][2])'
| |-FunctionDecl 0x10933db08 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[4])'
| |-FunctionDecl 0x1093539a8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[2][2])'
| `-FunctionDecl 0x1093552d8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[2])'
Here you see the compiler has emitted a different version of the print_arr function for every permutation of array size we've used. This isn't exactly what you could reasonably call "one function", it's actually many functions that have each been automatically generated by the compiler. It's a tiny amount of text to write in a cpp file, but the actual amount of code that gets generated is significant.
An alternate way to solve this problem is to just include type information in the print_arr function. Here's an example of an implementation that is WYSIWYG, and will let you do the same thing though you need to provide the type metadata manually:
const int *print_arr(const int *arr, const int rank, const int *lengths)
{
const char *p_sep = "";
printf("{");
if (rank > 1) {
for (int i = 0; i < lengths[0]; i++) {
printf("%s", p_sep);
arr = print_arr(arr, rank - 1, &lengths[1]);
p_sep = ", ";
}
} else {
for (int i = 0; i < lengths[0]; i++) {
printf("%s%d", p_sep, *arr++);
p_sep = ", ";
}
}
printf("}");
return arr;
}
And here's how you would use it with the same example arrays:
int main(int argc, char **argv)
{
int arr1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
print_arr(&arr1[0][0], 2, (int[2]){3, 4});
printf("\n");
int arr2[3] = {13, 14, 15};
print_arr(&arr2[0], 1, (int[1]){3});
printf("\n");
int arr3[3][2][2] = {{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}};
print_arr(&arr3[0][0][0], 3, (int[3]){3, 2, 2});
printf("\n");
return 0;
}
Output:
jon#promptC$ ./test
{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
{13, 14, 15}
{{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}}
This approach has a few advantages, the most important being that the compiler emits pretty much exactly what's written. It also forces you to be very explicit in the code, which is probably good in this case.
As always with C and C++ you need to know what's most appropriate for the situation you find yourself in.

How to return a struct which contains an array pointer from a function?

I have this struct and declaration in .h file,
struct strct
{
int *arry;
};
strct func01();
and this function in .cpp file,
strct func01()
{
int temp_arry[] = {5, 6, 7, 8, 9};
strct rtrn;
rtrn.arry = temp_arry;
return rtrn;
}
and i call the function like,
strct test = func01();
printf("%d", test.arry);
It prints some random numbers. I want to print the full array.
Before we start, let's recall the behavior of the sizeof operator:
Case of : int *
int *arry;
int iSize = sizeof (arry); <-- Return size of pointer and NOT number of elements
Case of : int []
int temp_arry[] = {5, 6, 7, 8, 9};
int iSize = sizeof (temp_arry); <-- Return total memory size allocated for 5 elements
You understand now that the composition of your structure does not allow you to determine the number of elements of your int *arry struct member. Therefore, you don't know how many element you should display.
If you wish to keep your program without using the STL: vector, array, ... you must complete your structure as follows:
struct strct
{
int size; // Contains the number of elements to use
int *arry;
};
strct func01();
strct func01()
{
strct rtrn;
int tab_size = 5;
// it is a temp variable. Destroyed when function ends.You can not use it !
int temp_arry[] = {5, 6, 7, 8, 9};
// This table is allocated with new and can be used
int *permanent_arry = new int [tab_size];
for (int i=0; i<tab_size; i++)
permanent_arry[i] = i;
rtrn.arry = permanent_arry;
rtrn.size = tab_size;
return rtrn;
}
int main ()
{
strct test = func01();
for (int i=0; i<test.size; i++)
printf("%d ", test.arry[i]);
// dont forget to delete memory
delete [] test.arry;
}
First, this code is wrong because:
the lifetime of temp_arry[] is end after func01 returns.
you are printing a pointer, not an array.
Second, if you want to print the full array, you'd better redesign your code, for example, you may use vector to clean up your code. (this code needs C++ 11)
struct strct
{
std::vector<int> arry;
};
strct func01();
strct func01()
{
std::vector<int> temp_arry = {5, 6, 7, 8, 9};
strct rtrn;
rtrn.arry = temp_arry;
return rtrn;
}
strct test = func01();
for(auto i : test)
std::cout << i << " ";
Note: most of the time there's no point to use built-in arrays as return value, even though it will decay to a pointer prvalue.

c++ int array with values of 2 dimension int array (3d array)

I'm trying to make an array which contain int[][] items
i.e
int version0Indexes[][4] = { {1,2,3,4}, {5,6,7,8} };
int version1Indexes[][4] = { ...... };
int version15Indexes[][4] = { ... };
(total of 16)
int indexes[][][] = { version0Indexes,version1Indexes, .. };
anyone can suggest how to do so ?
Thanks
You can use an array of pointers to array:
int (*indexes[])[4] = { version0Indexes, version1Indexes, .. };
Either you inline your arrays inside indexes:
int indexes[][2][4] = {
{ { 1, 2, 3, 4}, {5, 6, 7, 8} },
{ {....}, {....} }
....
}
Or you make indexes an array of pointers:
int (*indexes[])[4] = { version0Indexes, version1Indexes, .... };
What you wrote in your question is not directly possible because, when used, an array variable is actually a pointer (that's why indices has to be an array of pointers).

Cannot convert vector<int> to int* for bool testPIN

For a class assignment I had to rewrite this code using vectors instead of arrays. I figured I would use the existing arrays and assign them as a vector. But I get:
error: cannot convert 'std::vector' to 'int*' for argument '1' to
'bool testPIN(int*, int*, int)'
How can I get around this error?
#include <iostream>
#include<vector>
using namespace std;
// Function Prototype
bool testPIN(int [], int [], int);
int main ()
{
const int NUM_DIGITS = 7; // Number of digits in a PIN
int cpin1[NUM_DIGITS] = {2, 4, 1, 8, 7, 9, 0}; // Base set of values.
int cpin2[NUM_DIGITS] = {2, 4, 6, 8, 7, 9, 0};
int cpin3[NUM_DIGITS] = {1, 2, 3, 4, 5, 6, 7};
vector<int> pin1(cpin1, cpin1+7) ;
vector<int> pin2(cpin2, cpin2+7) ;
vector<int> pin3(cpin3, cpin3+7) ;
if (testPIN(pin1, pin2, NUM_DIGITS))
cout << "ERROR: pin1 and pin2 report to be the same.\n";
else
cout << "SUCCESS: pin1 and pin2 are different.\n";
if (testPIN(pin1, pin3, NUM_DIGITS))
cout << "ERROR: pin1 and pin3 report to be the same.\n";
else
cout << "SUCCESS: pin1 and pin3 are different.\n";
if (testPIN(pin1, pin1, NUM_DIGITS))
cout << "SUCCESS: pin1 and pin1 report to be the same.\n";
else
cout << "ERROR: pin1 and pin1 report to be different.\n";
return 0;
}
bool testPIN(int custPIN[], int databasePIN[], int size)
{................}
In these situations, it helps to read a good reference. You would need to get the vector's underlying data array:
testPIN(pin1.data(), pin2.data(), NUM_DIGITS))
If your implementation does not support C++11, you can do the following:
testPIN(&pin1[0], &pin2[0], NUM_DIGITS))
But if you have been asked to re-implement some code to use vectors, you may want to re-implement the testPIN function instead:
bool testPIN(const std::vector<int>& custPIN1,
const std::vector<int>& custPIN2);
and then just pass the vectors:
testPIN(pin1, pin2);
testPIN(&pin1[0], &pin2[0], NUM_DIGITS)
because the vector's internal memory structure is same with array.
Please check this.
How to convert vector to array in C++

How to initialize pointer to pointer with premade data?

I have a pointer to a pointer, since I can't pass dynamic arrays to functions. However, if I want to initialize that pointer-to-pointer with premade data, how can I set it since {a,b,c} notation for arrays won't work for pointers?
You can do this:
static int row1[] = {1, 2, 3};
static int row2[] = {4, 5, 6, 7};
static int row3[] = {8, 9, 10, 11, 12, 13};
static int *pptr[] = {row1, row2, row3};
At this point, pptr can be assigned to an int**:
int **p = pptr;
[This answer is only relevant if you need a double*. Your question was edited to say pointer to pointer - if that's what you need, this answer is not relevant.]
You can do this instead:
double fValues[3] = { 1, 2, 3 };
The variable fValues is already a pointer - array variables without the [] are pointers to the first element of the array. This is not a dynamic array, so you don't need to allocate/free its memory.
Assuming your function that takes a double pointer looks something like this:
void Func(double* pDbl) {...}
you'd call it like this:
Func(fValues);
You can create small dynamic arrays recursively something like this:
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct
{
int* pValues;
size_t Count;
} List;
const List ListEnd = { NULL, 0 };
List NewList(int Value, List SubList)
{
List l;
l.Count = SubList.Count + 1;
if (SubList.Count == 0)
{
l.pValues = malloc(sizeof(int));
}
else
{
l.pValues = realloc(SubList.pValues, l.Count * sizeof(int));
}
if (l.pValues == NULL)
{
// do proper error handling here
abort();
}
// moving data isn't necessary if the list elements are
// in the reverse order
memmove(&l.pValues[1], &l.pValues[0], SubList.Count * sizeof(int));
l.pValues[0] = Value;
return l;
}
void PrintDynArr(int* pValues, size_t Count)
{
while (Count--)
{
printf("%d\n", *pValues++);
}
}
int main(void)
{
int* p;
PrintDynArr(p = NewList(1,
NewList(2,
NewList(3,
NewList(4, ListEnd)))).pValues,
4);
free(p);
return 0;
}
Output:
1
2
3
4