Cannot convert char(*)[50] to char* in assignment - c++

Newbie question here...why does the following code only work with a 1D array but not a 2D array? Shouldn't it not make a difference whether b is pointing to the start of a 1D array or a 2D array, as long as it's a char* pointer (as it is)? I thought that the general notation [bound1][bound2] was an equivalent of [bound1*bound2], even over the assignment operation. Help?
main() //this works fine
{
char *b;
b = new char[50];
return 0;
}
.
main() //but this raises the error "Cannot convert char(*)[50] to char* in assignment"
{
char *b;
b = new char[50][50];
return 0;
}

char[50]; is array of 50 elements of type char. Each element has type char. So new char[50]; returns a pointer to first element: char * - pointer to char.
char[50][50] is NOT array of char. It is array of arrays. Each element has type char[50]. So new char[50][50]; returns a pointer to first element: char (*)[50] - pointer to char[50].
Declare b this way:
char (*b)[50];
Test: http://ideone.com/1zJs1O

If your were right with that [bound1][bound2] and [bound1*bound2] were equivalent you wouldn't have created a 2D array. The size of allocated memory, that's what your multiplication implies, is not the problem here, it's about different data types: A 1D array is simply not a 2D array and that's what the compiler is telling you. You should read about C++ type system and type safety.
What is type safety and what are the "type safe" alternatives?

Related

Difference between char** and char*

So I have a 2D array (I think) in my main:
char* map[width][height] = {MATRIX HERE};
And I'm passing it to a function:
bool canAccessEdge (char** map, int size, int currentPosX, int currentPosY);
I'm passing with with via:
canAccessEdge (*map, 10, playerStartPosX, playerStartPosY);
I want to traverse the map array and mark the positions that the player was already on. But I understand I can't change a value at an index in the function.
I understand that char map [][] would be an array and char *map is a pointer. So what is char* map [][]? Is there a work around without changing the prototype?
Sorry if these are dumb questions... I can't grasp pointers/arrays too well.
bool exitPossible (char** map, int size, int currentPosX, int currentPosY) {
...
*maze[currentPosX][currentPosY] = "V"; // Operand of '*' must be a pointer but has type "char"
(&maze)[currentPosX][currentPosY] = "V"; // Changes whole row and not the right position
&(maze)[currentPosX][currentPosY] = "V"; // Expression must be a modifiable lvalue (I assume it's immutable)
...
}
char[N] can degrade to char*. That does not mean that char[N][M] can degrade to char**. Beginners always make this assumption but it is not true.
char*[N][M] is something else again. That is not a 2D array of char (which seems to be what you want). A 2D array of chars is char[N][M]. With a 2D array of chars the correct syntax is
maze[currentPosX][currentPosY] = 'V';
Note the single quotes.
If you want to pass a 2D array of chars to a function then the simplest way is to declare the function with a 2D array of chars
bool exitPossible(char maze[N][M], ...)
but the reality is that maze here is a pointer to a 1D array, it's actually not possible to have an array as a function parameter in C++. So the truthful declaration of the function is
bool exitPossible(char (*maze)[M], ...)
Here we see what maze really is, a pointer to a 1D array (of size M). And this completes the first paragraph above. A 2D array char[N][M] degrades not to char** but to char (*)[M]. If this seems complicated then you are right, a good book is needed to explain it fully.
Note that in all this discussion N and M are constants. In C++ array sizes cannot be variable.

Asterisk after new in 2d array

What is the use of a * after new int in this code? Why can't we write 2d array without * after new int?
int *p1=new int[3];
int *p2=new int[3];
int **pData= new int*[2];
The use of the * after new int is, as you said, for the 2d array.
Without the *, it is simply a 1d array.
There is a similar question which could be useful:
link
new int*[2] says to allocate storage for an array of 2 int*. There's nothing special here: int* is the name of the type being created. The code uses that array of int* to create a 2-dimensional array, but that's in the rest of the code; new int*[2] on its own is simply an array of pointers.
But, yes, you can create a 2-dimensional array directly, without that intervening layer of pointers:
int (*p)[3] = new int[2][3];
This defines p to be a pointer to an array of 3 int. And, because the new expression gives the dimension for that array, you've got a 2-dimensional array. It acts just the way you'd hope for:
p[1][2] = 7;
std::cout << p[1][2] << '\n';
* is a pointer, check this answer out for an explanation of using pointers in C++

How to convert a vector to an array of a typdef type

I have a typedef defined in a header file as:
typedef unsigned char BYTE;
And I have the following code:
BYTE rgbPlaintext[] = {0x00};
rgbPlaintext* = &vec[0];
vec is an array of unsigned char that is populated by a file (no issue there). My issue is, the above code does not build successfully, all it says is syntax error : '=' at the line rgbPlaintext* = &vec[0];
How can I successfully point the array to the array that is in the vector that is of the underlying type of the typedef?
Thank you.
My issue is, the above code does not build successfully, all it says is syntax error : '=' at the line rgbPlaintext* = &vec[0];
You get the error because the compiler expects a right hand argument to the multiplication operator but instead found = which is not a valid operand for the multiplication operator. I get the feeling that a multiplication was not your intention.
How to convert a vector to an array of a typdef type
Vectors can not be converted to an array.
Perhaps you mean to copy the contents of the vector into an array. That's simple:
std::copy(vec.begin(), vec.end(), rgbPlaintext);
You need to be careful, however. If the array is smaller than the vector, then it will overflow and you get undefined behaviour.
How can I successfully point the array to the array that is...
Arrays do not point anything and you can not make them point anything. Arrays contain objects.
In this case the array rgbPlaintext contains a single element with the value 0x00. You can use the method I showed to copy contents of a vector to rgbPlaintext, but if the vector contains more than one element, the copy will overflow.
How would one know the size of an array needed if the vector that the array is based off of is populated by a data file?
The size of a vector can be known using std::vector::size(). But the size can not be known at compile time, so if you intend to copy the contents to an array and cannot limit the maximum size, then you cannot use an automatically or statically allocated array. You can use a dynamically allocated array, and for that, I recommend using a std::vector.
Copying a vector to another is simple:
std::vector<BYTE> rgbPlaintext = vec;
This is OK as long as BYTE is the same type as decltype(vec)::value_type. It does not matter if one type is an alias of the other.
For the code:
rgbPlaintext* = &vec[0]; // vec is an array of unsigned char
The syntax is incorrect rgbPlaintext* as said in another post.
To do the following:
How can I successfully point the array to the array that is in the vector that is of the underlying type of the typedef?
I'm going to assume that what you are really saying that vec is a vector from std that contains arrays of unsigned char's. If this is the case then I would do the following:
BYTE* rgbPlaintext = NULL;
rgbPlaintext = vec[0]; // any subscript of the list of arrays
cout << rgbPlainText[0] << endl; // return the first value at sub of array attained from vec
Here is small test program to clarify my understanding:
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char** argv )
{
typedef unsigned char NBYTE;
typedef vector<NBYTE*> TEST_ARRAYBYTE;
NBYTE *rgbPlaintext = NULL;
NBYTE testarray[] = {'2', '1'};
NBYTE testarray1[] = {'1', '2'};
TEST_ARRAYBYTE vec;
vec.push_back(testarray);
vec.push_back(testarray1);
rgbPlaintext = vec[0];
cout << rgbPlaintext[0] << endl;
rgbPlaintext = vec[1];
cout << rgbPlaintext[0] << endl;
}

Pointer dimensions when copying an address of multidimensional arra to a pointer

When we have a multidimensional array, and we hope to use a pointer to point to its address. In a book, it says we will do as following.
#include <stdio.h>
int main(){
int a[3][4][5];
int *p[5];
p = a;
return 0;
}
Now, I am quiet confused about the following points:
When I typed the code into CLion, it gives a warning:Incompatible pointer types 'int[5] *' and 'int[3][4][5]', and why is that?
Why does the pointer array *p contains 5 variables instead of 3 variables?
How to use this pointer *p?
Thanks.
1) Because... they are different pointer types! ;) Specifically, a is a three dimensional array of integers, while p is a one dimensional array of pointers to ints. Got that? a contains ints, p contains pointers to ints.
2) Because line int *p[5]; declares it to be 5 long. In C you define how big an array is by the number in the [].
3) Well, if you want p to point to a you would need to make some part of it point to a, as an example p[0] = a;

int ** vs int [ROWS][COLS] [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
casting char[][] to char** causes segfault?
I have a 2D array declared like this:
int arr[2][2]={ {1,2},{3,4}};
Now if I do:
int ** ptr=(int**) arr;
and:
cout<<**ptr;
I am getting a segmentation fault (using g++-4.0).
Why so? Shouldn't it be printing the value 1 (equal to arr[0][0])?
You can't cast a linear array to a pointer-to-pointer type, since int** doesn't hold the same data int[][] does.
The first holds pointers-to-pointers-to-ints. The second holds a sequence of ints, in linear memory.
You are attempting to assign a double pointer variable to an array... this has been covered exhaustively, see here for information on this. Furthermore, since you declared
int arr[2][2] = ...;
and then try to assign arr to a double pointer
int ** ptr = ... ;
which is guaranteed to not work, hence a segmentation fault. Furthermore, that statement int ** ptr=(int**) arr; is actually cast ing one type (i.e. [][]) to another type (i.e. **) despite they are of type 'int'. They are both different and the compiler will interpret that very differently...
You could do it this way:
int *ptr = &arr;
Now *(ptr + 1) will refer to the 0'th row, *(ptr + 2) will refer to the 1'st row and so on. The only onus on you is to not overstep the markers of where arr is used otherwise an overflow can happen or even a segmentation fault...
What you do now means creating of arrays of pointers where every pointer was explicitly casted. Therefore, you would have an array of pointers like (0x00001, 0x00002, 0x00003 and 0x00004).
When dereferenced, this pointers cause your segfault.
No, int ** is a pointer to a pointer to an int, but a 2-D array is an array of arrays, and &(arr[0][0]) is a pointer to an int.
I believe you should be doing this:
int *ptr = arr;
cout<<*ptr;
or this:
int *ptr = &arr[0][0];
cout<<*ptr;
Try
int *ptr = arr;
More Explanation:
You should assign an adress to the pointer, so it can be derefenced(i mean * operator). What you do is, pointing ptr to memory cell that has the adress a[0][0]. Therefore, you get a segmentation fault.
int arr[2][2] is not an array of arrays - it is a single 2d array. In memory, it is indistinguishable from int arr[4]
What you really want is
int (*ptr)[2] = arr;