int main(int argc, char** argv) {
char a[2][5]={"hell","worl"};
char **p;
p=a; // error here
cout<<*(*(a+1)+1);
cout<<endl;
cout<<(*a)[2];
return 0;
}
error:
C:\Dev-Cpp\main.cpp [Error] initializer-string for array of chars is too long [-fpermissive]
Why would you expect it to work? You declare p as char**,
and you try to assign a char[2][5] to it. The char[2][5]
will convert implicitly to a char (*)[5], but afterwards, you
have a pointer, and no further implicit conversions. (EDIT: except to void*.)
If you think about it, it should be obvious. If you dereference
a char**, you get a char*. And this char* must reside
somewhere in memory, since you have a pointer to it. So where
is it?
If you want to iterate over the outer array in your example:
char (*p)[5] = a;
std::cout << *p[0] << sdt::endl;
std::cout << *p[1] << sdt::endl;
Note that your expression *(*(a+1)+1) also supposes that you
have an array of pointers somewhere.
Or you can use the usual solution when working with C style
strings:
char const* const a[] = { "hell", "worl" };
and
char const* const* p = a;
In this case, you do have an array of pointers, which does
implicitly convert to a pointer to a pointer (the first element
of the array).
(Of course, the only time you'll really want to use C style
strings is with const variables with static lifetimes. In
most other cases, std::string is preferable.)
Other way to access the a[2][5] is,
char **p=(char**)a;
to get a[0]
printf("\n a[0] is [%s]", ((char*)p));
to get a[1]
printf("\n a[1] is [%s]", (((char*)p) + strlen(a[0])+1));
hope this helps.
Related
I am trying to pick up my C++; I have basic understanding of pointers and references; but when it comes to char pointer to array, it seems nothing works for me.
I have a small piece of codes here (omitted include and namespace statements), I have included my questions as comments below:
I have gone through at least 5 other questions on SO to try to understand it; but those answers didn't the answer I expected and to the extent that could help understand the actual issue there.
Could you kindly explain the problems I commented below with a bit of depth from the surface (so please don't dive into it directly)?
int main(){
// 1 this is a char pointer to a char;
char * c = new char;
*c ='A';
cout << c << endl; // this gives me memory address;
cout << *c << endl;// this gives me the value in the memory address;
// 2 this is a char array initialised to value "world";
char d[6] = "world";
cout << d[0] << endl; // this gives me the first element of char array;
// 3 this is char pointer to char array (or array of char pointers)?
char * str = new char[6];
for(int i=0;i<6;i++){ //
str[i]=d[i]; // are we assigning the memory address (not value) of respective elements here?
} // can I just do: *str = "world"; what's the difference between initialising with value
// and declaring the pointer and then assign value?
char * strr = "morning";
char b[6] = "hello";
cout << b << endl;
cout << (*str)[i] << endl; // why? error: subscripts requires array or pointer type
cout << str[1] << endl;
cout << (*strr)[1] << endl; // why? error: subscripts requires array or pointer type
}
// 1 this is a char pointer to a char;
Right.
// 2 this is a char array initialised to value "world";
Right, "world\0" is created by the compiler and is put in the read-only memory area of the program. Note that this is called a string literal. Then the string is copied over to the char array d.
// 3 this is char pointer to char array (or array of char pointers)?
That's a char pointer yes, a pointer to a single char.
// are we assigning the memory address (not value) of respective
elements here?
No, you're assigning the values of the elements. This is allowed because str[i] is the same as *(str + i) so you can use the same "array style" access with the pointer str. You're looping over the individual chars you have allocated with new and are assigning them the value of the chars in the char array d.
// why? error: subscripts requires array or pointer type
Because you already dereference str (which is pointing at the start of the 6 element char array) with * which gives you a char, then you try to use that char like an array with [1] which makes no sense. *str would give you 'w' (the first element). And str[1] would give you *(str + 1) which is 'o' (the second element), don't double up.
A small-big side note, string literals are of type const char[], not char[], they're placed in read only memory and thus they can not be altered by the program (don't write to them).
char * strr = "morning";
This is very very bad, it treats a const char[] as a char[], this has been deprecated in the standard for a while now and according to the current standard this is even illegal, yet compilers still allow it for some reason.
Because compilers allow this you could get some nasty situations like trying to modify the string literal:
char * strr = "morning";
strr[0] = 'w'; // change to "worning"
This will attempt to write to read-only memory, which is undefined behaviour and will probably/hopefully get you a segmentation fault. Long story short, use the appropriate type to have the compiler stop you before the code reaches runtime:
const char * strr = "morning";
side side note : don't forget to delete anything you allocated with new.
I have a char[][]
char c[2][2]={
{'a','b'},
{'c','d'}
};
How can I convert it to char**?
The objective here is to use the converted char** as an input for a main function, which only accepts char** as its input. Both C/C++ solutions are acceptable.
While you could easily switch from char[] to char*, the same is not possible with char[][] and char**:
your char[2][2] is a 2 dimensional array having all the elements stored contiguously. To access one element, the compiler computes the offset knowing the size of each row.
char** points to an array that contains pointers to char. To access one element, your compiler computes the offset of the pointer in the left-most, load that poitner, then access to the element.
Workaround:
char *pc[2]={c[0],c[1]};
cout << pc[1][1]<<endl; // prints out the same as c[1][1]
// you can pass `pc` when a `char**` is needed
Remark: this compiles perfectly. However, some functions with an argument like char **av expect in reality av[i] to be a null terminated c-string. In this case, although your code would compile, the results might not be what you expect (buffer overflow).
You cannot convert a char[2][2] to char**, you can only convert it to char(*)[2],
char (*p)[2] = c;
The above is a pointer to array-of-2-char. Note that you need this 2 and cannot just write char** p, since in the latter case you are not able to perform pointer arithmetic (the pointer won't know how many elements to "jump" when incrementing, and you won't be able to address the elements of your array (in this case the rows)).
You could pass the array into the function like this:
char c[2][2] = {
{'a','b'},
{'c','d'}
};
char* x[] { c[0], c[1] };
func(x); // Assuming something like: void func(char** p);
NOTE: Although this answer may explain/illustrate the problem quite well other answers are preferable that recommend creating an automatic variable char*[2]; rather than allocating with new as this answer does.
Original answer:
The problem is char c[2][2] is a contiguous block of char. The compiler allocates only 4 char objects.
When you build an array of arrays (char** c) you need to manually allocate an array of pointers to char and then allocate (or assign) and array of char to each of those pointers.
So to convert your array char c[2][2] to an array of arrays you have to first create the array of pointers and then assign the array of the first element of each array of char to that.
Something like this:
void func(char** c)
{
for(int x = 0; x < 2; ++x)
for(int y = 0; y < 2; ++y)
std::cout << c[x][y] << ' ';
std::cout << '\n';
}
int main(int, char* argv[])
{
// one contiguous block of 4 chars
char c[2][2]={
{'a','b'},
{'c','d'}
};
char** param = new char*[2]; // create your own pointer array
param[0] = &c[0][0]; // assign the first element of each char array
param[1] = &c[1][0];
func(param); // call your func
delete[] param; // cleanup
}
If you have C++11 you can use a smart pointer to prevent memory leaks if an exception is thrown or someone forgets to delete.
int main(int, char* argv[])
{
// one contiguous block of 4 chars
char c[2][2]={
{'a','b'},
{'c','d'}
};
// use a smart pointer
std::unique_ptr<char*[]> param(new char*[2]);
param[0] = &c[0][0];
param[1] = &c[1][0];
func(param.get()); // now if this throws, no memory leak
// delete[] param; // NO NEED TO DELETE
}
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x)
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str);
cout << str << endl;
return 0;
}
Please tell me why this program is giving compilation Error.I am using the g++ compiler
Error :temp1.cpp:16:8: error: cannot convert ‘char (*)[6]’ to ‘char**’ for
argument ‘1’ to ‘void f(char**)’
Arrays can be implicitly converted to pointers, but that doesn't mean that the implicit "pointer equivalent" already exists.
You are hoping that f(&str); will implicitly create both a pointer to str and a pointer to that pointer.
This small (working) change illustrates this point:
int main()
{
char str[]="hello";
char *pstr = str; // Now the pointer extists...
f(&pstr); // ...and can have an address
cout << str << endl;
return 0;
}
You are passing pointer of constant char to the function but in function you are taking it as pointer of pointers. That is the problem. I commented out below where the problem lies.
[Off topic but N. B. : Arrays and pointers are different concept.]
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x) //**x is pointer of pointer
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str); //You are passing pointer of constant char.
cout << str << endl;
return 0;
}
You're going to run into a serious problem with your function f since &str and &str[0] both evaluate to the same value ... as other posters have pointed out, these operations point to different types, but the actual pointer r-value will be the same. Thus in f when you attempt to double-dereference the char** pointer x, you're going to get a segfault even if you attempted something like a cast to massage the type differences and allow compilation to happen with errors. This is because you are never getting a pointer-to-pointer ... the fact that &str and &str[0] evaluate to the same pointer value means that a double-dereference acually attempts to use the char value in str[0] as a pointer value, which won't work.
Your problem is that you're treating arrays as pointers, when they're not. Arrays decay into pointers, and in this case, it doesn't. What you're passing in is a char (*)[6] when it expects a char **. Those are obviously not the same.
Change your parameter to char (*x)[6] (or use a template with a size parameter):
template <std::size_t N>
void f(char (*x)[N])
Once inside, you try to increment what x is pointing to. You can't increment an array, so use an actual pointer instead:
char *p = *x;
p++;
*p = 'a';
All put together, (sample)
template <std::size_t N>
void f(char(*x)[N])
{
if (N < 2) //so we don't run out of bounds
return;
char *p = *x;
p++;
*p = 'a';
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does this C statement mean?
What does this expression mean?
char *(*c[10])(int **p);
c is an array of 10 function pointers that return a char* and take a int** as an argument.
(*c[10])
^^^^ = array of 10
(*c[10])
^ = function pointer
So right now we have an array of 10 function pointers.
char *(*c[10])
^^^^^^ = returns a char*
char *(*c[10])(int** p)
^^^^^ = takes a int** as an argument
Array of 10 function pointers that return a char* and take a int** as an argument.
NOTE: If you write code like this you deserve to be slapped in the face.
cdecl is a nice tool to translate C gibberish into English
$ cdecl explain 'char * (*c[10]) (int **)'
declare c as array 10 of pointer to function (pointer to pointer to int) returning pointer to char
Some examples, and a snippet at the end that uses the decl.
1. Pointer to a function:
void (*foo)(void);
Would give you a function pointer foo which takes no parameters and returns nothing.
Ex. A:
void fun_1(void)
{
...
}
foo = fun_1;
foo(); /* this would call fun_1() */
Ex. B:
char (*bar)(int);
Would give you a function pointer bar which takes 1 parameter as integer and return a char.
char fun_2(int x)
{
if (x == 50)
return 'a';
return 'Z';
}
char v;
bar = fun_2;
v = bar(50); /* this would call fun_2() with 50 as parameter and return 'a' */
2. Pointer to a pointer
int **p; is a pointer that points to a pointer of type int.
Ex. C:
int y[3] = {4, 3, 6};
int *w = &y[0];
int **z = &w;
printf("print: %d ", **z);
printf("%d ", *++(*z));
printf("%d\n", *(*z+1));
print: 4 3 6
3. Function returning a pointer
Ex. D:
char *zez(char *s)
{
s = "def";
return s;
}
char *str = "abc";
printf("%s - ", str);
printf("%s\n", zez(str));
abc - def
4. Function pointer to a function returning a pointer
Creating a function pointer to zez()
Ex. E:
char *(*ptr_zez)(char *);
ptr_zez = zez;
printf("ptr: %s - ", str);
printf("%s\n", ptr_zez(str));
ptr: abc - def
5. Array of function pointers, to function returning a char pointer, taking a char pointer
Ex. F:
char *(*c[10])(char *);
c[0] = zez;
printf("c[0]: %s - ", str);
printf("%s\n", c[0](str));
c[0]: abc - def
6. "Declare c as array 10 of pointer to function (pointer to pointer to int) returning pointer to char"
char *cumlade(int **p)
{
char *c;
int i;
if ((c = malloc(sizeof(char) * 7)) == NULL) {
fprintf(stderr, "Unable to reserve 7 bytes\n");
exit(0);
}
for (i = 0; i < 6; ++i) {
c[i] = (unsigned char)*(*p+i);
}
c[6] = '\0';
return c;
}
int main(void)
{
int t[3][3] = {{97 ,98, 99}, {100, 101, 102}};
int *u = &t[0][0];
int **v = &u;
char *ex;
char *(*c[10])(int **p); /* <-- the fun */
c[0] = cumlade;
c[1] = cumlade;
ex = c[0](v);
printf("EX: %s\n", ex);
free(ex);
ex = c[1](v);
printf("AX: %s\n", ex);
free(ex);
return 0;
}
EX: abcdef
AX: abcdef
c is an array of 10 pointers to functions taking a pointer to pointer to int as its parameter and returning a pointer to char.
Type declaration involves three operators: array [SIZE], pointer * and function (type1 param1, type2 param2, ...). Remember that all the three operators are right-associative.
char *(*c[10])(int **p);
Let's add more parenthesis to make the associativity more clear.
char *((*(c[10]))(int *(*p)))
Start from c, the variable.
c[10] means "c is an array of 10 elements, but each element is a ..."
Then see the * beside it. *(c[10]) means "c is an array of 10 elements, each element is a pointer pointing to ..."
Then (*(c[10]))(int *(*p)) means "c is an array of 10 elements, each element is a pointer to a function, which returns ..." Using similar methods we see the function takes one parameter which is "a pointer to a pointer to an int".
Then *((*(c[10]))(int *(*p))) means "c is an array of 10 elements, each element is a pointer to a function, which returns a pointer to a ..."
Finally char *((*(c[10]))(int *(*p))) means "c is an array of 10 elements, each element is a pointer to a function, which returns a pointer to a char". That's it.
I find the Clockwise/Spiral Rule very useful. See http://c-faq.com/decl/spiral.anderson.html
But I'd rather add more brackets than using spirals.
ok now the answer you have, it is an array of function pointer, but is there clean(er) way to write code like this? Yes there is, and I am sure this code might be understood at the first glance:
typedef char *(*weirdFuncPtr)(int **p);
weirdFuncPtr funcPtrArray[10];
Btw. usually I avoid typdefs - I use them when declaring function pointers though. This makes it easier to understand this sort of C code (C is an abbreviation for Cryptic, is it?)
It declares an array of function pointers. There are 10 elements in the array (from c[10] part of the declaration). the function to which these pointers can point will return char* and takes only one parameter i.e pointer to pointer to integer (int **p)
Take a look at the first answer to this question How can I use an array of function pointers?
there you will find another example of declaring function-pointer array and it may end your confusion.
If you are looking for intuitive explanation for this,
http://www.geeksforgeeks.org/archives/16841
They explained this using postfix order evaluation, just like expression evaluation.
I have the following function in C++ :
char** f()
{
char (*v)[10] = new char[5][10];
return v;
}
Visual studio 2008 says the following:
error C2440: 'return' : cannot convert from 'char (*)[10]' to 'char **'
What exactly should the return type to be, in order for this function to work?
char** is not the same type as char (*)[10]. Both of these are incompatible types and so char (*)[10] cannot be implicitly converted to char**. Hence the compilation error.
The return type of the function looks very ugly. You have to write it as:
char (*f())[10]
{
char (*v)[10] = new char[5][10];
return v;
}
Now it compiles.
Or you can use typedef as:
typedef char carr[10];
carr* f()
{
char (*v)[10] = new char[5][10];
return v;
}
Ideone.
Basically, char (*v)[10] defines a pointer to a char array of size 10. It's the same as the following:
typedef char carr[10]; //carr is a char array of size 10
carr *v; //v is a pointer to array of size 10
So your code becomes equivalent to this:
carr* f()
{
carr *v = new carr[5];
return v;
}
cdecl.org helps here:
char v[10] reads as declare v as array 10 of char
char (*v)[10] reads as declare v as pointer to array 10 of char
A pointer to pointers is not the same as a pointer to arrays.
(In particular, notice how sizeof(*ptr1) is sizeof(char)*6, whereas sizeof(*ptr3) is sizeof(char*) — this has serious ramifications for pointer arithmetic.)
new char[5][10] gives you a char (*)[10] (which has absolutely nothing to do with function pointers, by the way), because the pointers and chars are laid out in that fashion in memory (my second example).
This is not the same as char** (which represents a different layout), so a conversion between the two makes no sense; hence, it is disallowed.
So your function's return type must be char (*)[10]:
char (*f())[10] {
char (*v)[10] = new char[5][10];
return v;
}
Of course, this is really ugly, so you're far better off with a std::vector<std::string>.
This FAQ entry explains it best, under the title "Conversions".
Because char** and char (*)[10] are two different types. char** is a pointer to pointer(to char), while char (*)[10] is a pointer to an array(of size 10) of char. Resultantly, the moving step of char** is sizeof(void *) bytes which is 4 bytes on win32 platform, and the moving step of char (*)[10] is sizeof(char) * 10 bytes.
Example
char *c = NULL;
char **v = &c;
cout << typeid(v).name() << endl;
cout << (void*)v << endl;
v += 1;
cout << (void*)v << endl;
char d[10];
char (*u)[10] = &d;
cout << typeid(u).name() << endl;
cout << (void*)u << endl;
u += 1;
cout << (void*)u << endl;
Output
char * *
0034FB1C
0034FB20
char (*)[10]
001AFC50
001AFC5A
To use char (*)[10] as a function's return type(or as input/output parameter of the function), the easiest and most readable way is to use a typedef:
// read from inside-out: PTRTARR is a pointer, and, it points to an array, of chars.
typedef char (*PTRTARR)[10];
Note that it can easily be mixed up with typedef of an array of pointers, if not careful:
// operator[] has higher precedence than operator*,
// PTRARR is an array of pointers to char.
typedef char *PTRARR[10];
Reference
Arrays and Pointers