c++ 2 dimensional static array compatible with 2 dimensional dynamic pointer - c++

Is there a way to declare 2 dimensional static array which is compatible with the dynamic pointer (TYPE**) ?
char strs1[2][256] = { "String 1", "String 2" }; // Static
What I want is to assign it to
char **strs2 = strs1;
Well, I can do something like that:
std::array<std::array<char, 256>, 2> arr = {"String 1", "String 2"};
char *temp[2] = { (char*)&arr[0], (char*) &arr[1] };
char **strs = (char**)temp;
cout << strs[0] << endl;
cout << strs[1] << endl;
// Output
String 1
String 2
But is there a better and simpler way to achieve the same result ?

char** can never be a way to reference a an array of arrays (there are no two-dimensional arrays in C/C++) because it doesn't have the information on the inner array size. In particular, there is no way compiler can generate a proper access code in following snippet:
char** arr = initialize_by_hack();
arr[2][4] = '42';
Here, to calculate second offset (4) compiler needs to know the size of element array - but is is nowhere in the code and not available.

No, you cannot change the fact that a two-dimensional array is incompatible with a T**.
You can only perform hacky workarounds like the one you posit in your question, or remedy the mistake or design flaw that initially led you to the requirement.
Since you're writing C++: why not use proper, modern, type-safe technologies rather than native arrays and a mess of pointers? A simple Matrix<T,W,H> class template that wraps a statically allocated T[W*H] but exposes two-dimensional indexing would be nice. Then just pass it around by reference (or, if you really must, by pointer).

Related

C++ writing to myArray[0] and setting myInt = myFloat, why is this working?

I'm playing with a function to get used to some C++ syntax.
Now I think, I might have misunderstood:
I'm writing to a static (?) array I had defined as myArray[0] for experimenting.
So it seems NOT to be static, but sizeof(myArray) always returns 0 (?)
but I can find mem address for each item (while I have no idea, how to get the number of items this way).
The other thing I don't understand, is why I can write myInt = myFloat?
So, what IS a static array? And should I better use <vector> for an array of undefined length?
(You could find the whole code here int2bin main.cpp)
#include <iostream>
//#include <regex>
int main()
{
while(true) {
//VARS
unsigned int arrBin[0], intNum; //working, if set [0]! NOT static???
unsigned int *pArr0 = &arrBin[0];
unsigned int *pArr1 = &arrBin[1];
std::cout << sizeof(arrBin) << '\n'; // 0 => sizeof() here items and not mem space?
std::cout << pArr0 << '\n';// 0x7fff12de6c38
std::cout << pArr1 << '\n';// 0x7fff12de6c3c
int i;
float refNum;
std::cout << "\n\nEnter a number to convert: ";
// GET INPUT
std::cin >> refNum; // float
intNum = refNum; // get int of the dec for comparing. Why does this "int = float" work???
unsigned int arrBin[0]
The size of an array variable must not be 0. The program is ill-formed. Don't do this.
unsigned int *pArr1 = &arrBin[1];
Here, you use subscript operator beyond the bounds of the array (beyond one past last element), so the behaviour of the program is undefined. Don't do this.
(while I have no idea, how to get the number of items this way).
The number of items is 0 (or would be if that was allowed in the first place).
The other thing I don't understand, is why I can write myInt = myFloat?
You haven't even declared such identifiers.
I'm writing to a static (?) array I had defined as myArray[0] for experimenting.
By 'static' you probably mean 'fixed-sized'. static means something totally different, see https://www.geeksforgeeks.org/static-keyword-cpp/.
So it seems NOT to be static
It is not static, hence, it's not surprising that it's not static.
but sizeof(myArray) always returns 0
Its size is 0, as the size of 0 was specified. While this is not supported by the standards, it's possible that some compilers allow it.
but I can find mem address for each item (while I have no idea, how to get the number of items this way).
&arr[i] yields the address.
The other thing I don't understand, is why I can write myInt = myFloat?
Integer numbers are always real numbers, but real numbers are not always integer numbers. So, how would you store 0.5 as an integer? You could cast it or you could round it.
So, what IS a static array?
In the link I have provided you, it is mentioned that static variables in a function are variables for whom memory is allocated for the whole duration of a program. Hence, a static array is an array declared with the static keyword for which space are allocated for the whole lifecycle of your program. No such array was declared in your function.
And should I better use for an array of undefined length?
This is opinionated. You could create a pointer and navigate to items using pointer arithmetics, achieving the same behavior as with arrays, but without the length being fixed and with a slightly different syntax. Or you could use a library, a vector or whatever fits your task and taste.

Trying to understand C++ pointers and data type initializations

I am trying to learn C++, I have a fair bit of experience in C# and the 2 languages are so dissimilar and I am having trouble understanding data types and pointer variants of data types and the initialization of them, please consider the code below:
wchar_t *array = new wchar_t[10]; //Declaring a pointer of wchart_t and initializing to a wchar_t array of size 10 ?
auto memAddressOfPointer = &array; //auto is resolving memAddressOfPointer to a pointer of a pointer?
cout << array << endl; //Printing the memory address of array not the object created above?
cout << *array << endl; //Getting the actual value of the object (empty wchar_t array of size 10 in bytes?
cout << &array << endl; //Printing the address of the obj?
cout << memAddressOfPointer << endl; //Printing the address of the obj ?
My question is why would I create a pointer and initialize it? Why not just create an array of wchar_t? like:
wchar_t array [10];
I refer to this stack post as well:
Unable to create an array of wchar_t
Thank you for your consideration.
If you know the size of the number of elements you need to put in the array, then just use the array i.e., wchar_t arr[10];.
If you don't know the size, you can create the array at runtime using dynamic memory allocation with the required size i.e., wchar_t *arr = new wchar_t[required_size]. Once the memory is allocated, you need to deallocate it using delete[] operator for arrays and delete for non-array pointers. However I highly recommend you don't do that and instead either
Use std::wstring in this particular case which will automatically handle this for you.
Use std::vector for everything else if you can. It's a dynamic array which will grow automatically. No manual memory management etc.
In case you have to use pointers, use a smart pointer like unique_ptr or shared_ptr. The advantage of using smart pointers is that they will automatically clean up once they go out of scope.
If you know the extent of the array when writing the program, there's absolutely nothing wrong with wchar_t array [10];. If 10 is a fixed (constexpr) number - stick with that.
What wchar_t *array = new wchar_t[10]; lets you do is to let 10 be a number that you find out in run-time. You can change 10 to x and let x be a number that the user supplies or that you calculate somehow. wchar_t array [x]; when x is not a constexpr is on the other hand not valid C++ (but is available as an exension, called VLA, in some implementations).
Note: One downside with using new is that you need to make sure you delete the same pointer. This is not always simple. Using these raw pointers is therefore not what you usually want to do. Instead, use a smart pointer, like std::unique_ptr<wchar_t[]>, and the resource will be delete[]d when the pointer goes out of scope.
The advantages of creating a pointer instead of an array are the dynamic allocation that you can take advantage of and also the properties of the pointer that might help.
Consider the following code that represent the dynamic allocation and reallocation:
int x;
cin >> x;
int *oldArr = malloc(x * sizeof(int));
for(int i = 0; i < x; i++)
arr[i] = i;
cin >> x;
arr = realloc(arr, x * sizeof(int));
Here is another example that shows one of the pointer features which also you can use along with arrays.
int arr[5] = {1, 2, 3, 4 ,5};
int *ptr = arr;
cout << *ptr;
ptr++;
cout << *ptr;
cout << *(ptr + 1);
Despite these advantages and others, I think that the example you are presenting of using pointers instead of arrays is just for academic purposes to understand how to work with pointers in order to build more complex data structures using pointers in future lessons as you are using constant size arrays.

How to pass reference to a string array as a function parameter in runtime when array size is unknown in C++?

The following piece of code works fine. Problem is I need it to work when size of array is unknown. In the example below I have hardcoded the values to 2. In the real world I do not know the size. Is there a way to modify the code so that it works even when size of the array is not known.
void namesArray(std::string (&numList)[2], std::string name)
{
//This is just place holder code. Please ignore the logic.
numList[ 0 ] = "Peter" + name;
numList[ 1 ] = "Bruce" + name;
}
int main()
{
std::string nameList[2];
namesArray( nameList, "Parker");
std::cout << nameList[0]<< std::endl;
std::cout << nameList[1] << std::endl;
return 0;
}
I CANNOT use any other datatype (eg: Vectors) except Arrays due to external limitations.
Edit: When I say the size is unknown, what I mean is the size of the Array is not known until runtime.
Also, what I am presenting is an over simplification of my actual code. The function accepts only arrays.
UPDATE: Thank you all for the solutions offered. Looks like the code I have already authored worked in my solution. I know it's wierd to use arrays when vetors offer more flexibility. However, when dealing with legacy code you sometimes don't have a choice. THANKS A LOT FOR ALL THE ANSWERS TO EVERYONE WHO RESPONDED. IT WAS VERY INFORMATIVE.
If I understood your question well, you can use template mechanism to array size deduction:
#include <iostream>
#include <string>
template <size_t N>
void namesArray(std::string (&numList)[N], std::string name) {
//This is just place holder code. Please ignore the logic.
numList[ 0 ] = "Peter" + name;
numList[ 1 ] = "Bruce" + name;
}
int main() {
std::string nameList[5];
namesArray( nameList, "Parker");
std::cout << nameList[0]<< std::endl;
std::cout << nameList[1] << std::endl;
return 0;
}
You got presented several solutions. I'd like to present another, one that is an abstraction which incorporates several solutions. Take a gsl::span (or a std::span if you are from the future).
A span is generalized a view on a contiguous sequence of elements. And a powerful abstraction.
You want to pass an array of static size? A span can be constructed from one via a template constructor.
You want to pass a pointer and a size? span got you covered there as well.
A container like std::vector or std::array? No problem.
Use a span if all you care about is the sequence property, and not what the sequence itself is.
The simplest solution is to pass the size in with the array:
void namesArray(std::string *numList, std::size_t numCount, std::string name)
This will probably work for you -- you need to know the size of the array when you pass it in, but it doesn't require that you be working with a stack array from that scope, and in general usage you're more likely to have access to the size of the array than to be creating the array in the same scope that you're calling the function. It also makes things much more explicit and, if you switch to heap arrays instead of stack arrays, it still works fine.
Here's the thing: You always know the size of the array. It's literally impossible to write code that creates an array of an unknown size. You can (un)intentionally forget the array size, but at some point, it has to be known, because you literally can't create the array otherwise. You might only know it at runtime, because it's, say, defined by user input, but that just means it's in a variable, and you still know it, you just don't have it predefined at compile time.
Also, if the array size is defined at runtime, you're using heap arrays, and the other solution won't work for that.

create global dynamic array inside the function

I am writing a programm in C++. In my programm I need to create an array with dynamic size inside one function, but this array should be also accessable for other functions. I will not post here my code, just write one dummy example.
char *array;
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
void function_2() {
array[0] = "new value 1";
}
int main() {
function_1();
function_2();
delete[] array;
}
My question is: I am not sure, if the array will exist outside the function_1, where it was initialised, until I delocate a memory of array.
Or the array will have just a behaviour of local variable inside one function. What means, that the memory, which stores the array values, will be dellocated after the function is finished and the memory addresses of my array can be rewroten with something else later in my programm.
Thank you.
First, of course it will exist outside, that's all what dynamic allocation is about. Also, the variable itself is global. Also, it should be a char const** array; and the allocation should be new char const*[3] (note the square brackets). The const because you won't change the contents of the strings here.
Second, don't do that. Just put it in a class and use a std::vector!
#include <vector>
class Foo{
public:
function_1(){
_array.push_back("value 1");
_array.push_back("value 2");
_array.push_back("value 3");
}
function_2(){
_array[0] = ("new value 1");
}
private:
std::vector<std::string> _array;
};
int main(){
Foo f;
f.function_1();
f.function_2();
}
Even better, have a std::vector<std::string>, so you can safely modify the contents without having to worry about memory management. Though, to this won't be a single block any more. Now I got to ask, how exactly do you want to pass the buffer to the socket?
You actually have a fatal error in your function_1(). The following code will cause array to point to a character, with the value 3. Then, it will overwrite various parts of neighboring memory, basically causing a buffer overflow.
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
What you probably want to do is create something like:
char **array;
array = new char*[3];
array[0] = new char[strlen(...)];
array[0] = strncpy(array[0], ..., strlen(...)];
// etc
A much safer and cleaner way of accomplishing this would be to do what Xeo is suggesting, and using a std::vector instead of a plain array.
Since array is global, it is visible to other functions. Memory allocated with new[] stays around until it is freed by delete[].
It will exist and be global, because the char * array pointer is global.
The memory that you allocate in function1 will stay allocated after the program exits the scope of the function and will work as expected in functions 2 and 3. Notice however, that behaviour is undefined if you call functions 2 and 3 before function one. In general though, what you're trying to do here looks like bad design, but for the sake of the question I won't bug you about that now :)
It would greatly improve the clarity of your code if you'd:
use a std::vector, especially if you plan to resize it later
use a std::string to represent strings
pass the array or vector by reference to the functions that need it.
int main() {
std::vector<std::string> vect;
function_1(vect);
function_2(vect);
}
where your functions look like:
void function_1(std::vector<std::string> & Vect)
typedefs help manage the argument types
This way you won't have to worry about leaks as the vector will deallocate itself when out of scope.

Macro to both get (void*) address of item and length, for arrays and structs

I'm trying to design a macro to produce several related data structures related to things that need initialization. The code has to compile under both C and C++. The goal is to have something like:
MUNGE_THING(struct1);
MUNGE_THING(array1);
turn into something equivalent to
munge_thing((void*)&struct1, sizeof(struct1));
munge_thing((void*)array1, sizeof(array1));
Is there any syntactic stuff I can surround the macro argument with so that it will handle both arrays and structure correctly both when taking the address and when getting the size? The most likely context will be in the constant declaration of an initialization list.
If that isn't possible, and it's necessary to use separate macros for structures and arrays, what would be the best syntax to ensure that passing something incorrectly will yield a compile error rather than bogus code?
In "old" C, prepending an array address with "&" would yield a warning, but not prevent compilation. In C++, it seems to yield the address of a location which stores the address of the array.
The MUNGE_THING macros are going to be within another macro that will be invoked multiple times with different definitions of MUNGE_THING, so having separate macros for arrays and structs would be irksome. The best approach I can figure would be to give MUNGE_THING an extra argument for the "optional" ampersand, but that somehow seems ugly.
If the array is in fact an array (which seems to be required for the sizeof to work), why don't you just use the simple macro:
#define MUNGE_THING( x ) munge_thing((void*)&(x), sizeof(x))
That should work both for arrays and structs:
int array[10];
assert( (void*)array == (void*)&array );
You have tagged the question as both C and C++, in C++ you can use templates and avoid the macros all together.
I'm not sure what problem you are having with &array1. This C++ worked exactly as expected (all values the same)
int main(int argc, char* argv[])
{
int array1[10];
printf("%x %x\n", array1, &array1);
cout << array1 << " " << &array1 << endl;
void* ptr1 = array1;
void* ptr2 = &array1;
printf("%x %x\n", ptr1, ptr2);
cout << ptr1 << " " << ptr2 << endl;
return 0;
}
Okay, I see my confusion. In C++, the type of &array is not compatible with the type of the array, and as the linked discussion notes, (&array)+1 is not the same as (array+1), but casting the unsubscripted pointers does in fact yield the proper results. The distinctions between arrays and pointers in C are very confusing. Thanks for the assistance.