PROBLEM: why can't auto-covert char [10][10] into char **

W

Wisdo

Hi All,

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

Regards
-Wisdo
 
T

tolgaceylanus

void print(char (*p)[128], int len)

definition should fix your problem. Functions that have 2 dimensional
arrays
as arguments need a hint to be able to offset the arrays properly. This
is
because these are arrays of arrays actually.

Hope this helps,

Tolga Ceylan
 
D

Daniel T.

Wisdo said:
Hi All,

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

Yes, char[][] is not the same as a char**. 'sex' isn't a pointer to a
pointer to a char.
 
J

Jim Langston

Wisdo said:
Hi All,

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

Regards
-Wisdo

Because char [10][10] is not an array of pointers, it is a two dimentional
array of characters.
The memory is allocated and used about the same way as char [100] and you
can test that yourself.

This prints out Male and Female twice. Pick the one you like best.

void print( const char p[][128], const int length )
{
for ( int i = 0; i < length; ++i )
std::cout << &p[0] << std::endl;
}

void print2( const char* p, const int width, const int length )
{
for ( int i = 0; i < length; ++i )
std::cout << &p[width * i] << std::endl;
}

int main()
{
char sex[2][128] = {"Male", "Female" };
print( sex, 2 );
print2( reinterpret_cast<const char *>( sex ), 128, 2 );
}
 
F

Frederick Gotham

Wisdo posted:
Hi All,

char [10][10] to char ** is compile error. why?


Type mismatch, both before and after the array-to-pointer decay.

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.


Incorrect -- arrays yield well-defined behaviour in C++.

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?


Your speech is unintelligible.

Here's some sample code:

#include <cstddef>
#include <cassert>
#include <iostream>

using std::cout;
using std::size_t;

#define restrict /* Nothing */
#define nullptr 0 /* Until next standard */

size_t const buflen = 64;

void PrintNullTerminatedArrayOfPointersToStrings(char const *const restrict
*restrict p)
{
assert(p);
assert(*p);

do cout << *p++ << '\n';
while(*p);
}

void PrintNullTerminatedArrayOfStrings(char const *restrict p)
{
assert(p);
assert(*p);

do cout << p << '\n';
while(*(p += buflen));
}

int main()
{
char const *const restrict names1[] = {
"Michael","John","Philip","Barry","Thomas",
"Luke","Owen","Richard","Keith",nullptr};

char const names2[][buflen] = {
"Michael","John","Philip","Barry","Thomas",
"Luke","Owen","Richard","Keith", {0} };

PrintNullTerminatedArrayOfPointersToStrings(names1);

PrintNullTerminatedArrayOfStrings(*names2);
}
 
G

Greg Comeau

Hi All,

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

The problem is that you do not have an array of pointers,
you have an array or array's, so something like sex[1][2]
has to get to the right group of [128]'s. It's not sure
what you want here, but perhaps you want to pass each
sex and accept a char * instead.
 
G

Greg Comeau

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

The problem is that you do not have an array of pointers,
you have an array or array's, so something like sex[1][2]
has to get to the right group of [128]'s. It's not sure
what you want here, but perhaps you want to pass each
sex and accept a char * instead.


Oops if not obvious "array or arrays" should say "array of arrays"
 
N

Noah Roberts

void print(char (*p)[128], int len)

Yet another reason to just use the standard classes to your advantage
is that rather convoluted and entirely necissary definition.
 
P

Pierre Barbier de Reuille

Wisdo said:
Hi All,

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

Regards
-Wisdo

Simply, one (IMHO) convenient way to implement the print function is to
use template:

#include <iostream>

using namespace std;

template <size_t N>
void print(char p[][N], int len)
{
for(int i = 0 ; i < len ; ++i)
{
cout << p << endl;
}
}

int main()
{
char sex[2][128] = {"Male", "Female" };
print(sex, 2);
return 0;
}

Pierre
 
F

Frederick Gotham

Noah Roberts posted:
void print(char (*p)[128], int len)

Yet another reason to just use the standard classes to your advantage
is that rather convoluted and entirely necissary definition.


I see nothing convoluted about it, but then again I'm not afraid of C++.
 
J

Jim Langston

Wisdo said:
Hi All,

char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?

Regards
-Wisdo

Of course, since this is a c++ group, need to give you a modern equivalent.
(code snippets which I hope contain no typos)

#include <string>
#include <vector>

std::vector<std::string> Sex;

void print( std::vector<std::string>& p )
{
for ( std::vector<std::string>::iterator it = p.begin(); it != p.end();
+it )
std::cout << *it << std::endl;
}

Sex.push_back("Male");
Sex.push_back("Female");
 
J

Jerry Coffin

[ ... ]
#include <string>
#include <vector>

A couple minor omissions:
#include <iostream>
#include <iterator>

Though I'd include said:
std::vector<std::string> Sex;

void print( std::vector<std::string>& p )
{
for ( std::vector<std::string>::iterator it = p.begin(); it != p.end();
+it )
std::cout << *it << std::endl;
}

And then I'd use:

void print(std::vector<std::string const &p) {
std::copy(p.begin(), p.end(),
std::eek:stream_iterator<std::string>(std::cout, "\n"));
}

Or perhaps even:

std::eek:stream &
operator<<(std::eek:stream &os, std::vector<std::string> const &v) {
std::copy(v.begin(), v.end(),
std::eek:stream_iterator<std::string>(os, "\n"));
return os;
}

int main() {
std::vector<std::string> Sex;

Sex.push_back("Female");
Sex.push_back("Male");

std::cout << Sex;
return 0;
}
 
W

Wisdo

Greg Comeau дµÀ:
char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?
The problem is that you do not have an array of pointers,
you have an array or array's, so something like sex[1][2]
has to get to the right group of [128]'s. It's not sure
what you want here, but perhaps you want to pass each
sex and accept a char * instead.


Oops if not obvious "array or arrays" should say "array of arrays"


I want to know why C/C++ forbidden the covertion from char[][] to char **p.

as many guys said, the char [12][12] and char ** are different types,
and of course can't covert into each other.

but in C/C++, the char [12] and char *p are the same expect the latter
lost the length information.
i.e. in C/C++,

void f(char *p, int len);
char s[7] = "array";
f(s, 7); <-- it's OK.

but if we consider the same thing in two-dimenstion

void f(char **p, int with, int height);
char s[2][128] = { "Male", "Female" };
f(s, 2, 128); <-- this need auto-convertion from char[2][128] to char**
, but it's forbidden in C/C++.

I'm interesed in the regular design about C/C++ about this ban,
it's forbidden and what it want to avoid?


-Wisdo
 
W

Wisdo

Frederick Gotham дµÀ:
Wisdo posted:
Hi All,

char [10][10] to char ** is compile error. why?


Type mismatch, both before and after the array-to-pointer decay.

yes, they are type mismatch.
but whether they are type mismatch depends the type conversion rule.
if the two types can't convert into each other, then they are type mistach.

char [10] and char * are also differnet type, but we can do this

void print(char *p, int len);
char s[10] = "arrayStr";
print(p);

and we can't do this in 2-dimension.
void print(char **p, int w, int h);
char ss[2][10] = { "str1", "str2" };
print(p, 2, 10);

it's surprising, and i could ask why can't do this.
and the answer is they are mismatch.
so why char [10][10] and char ** are mismatch,
but char[10] and char * are not mismatch?

Maybe it's a little about the tradeoff of language design.
and i really want to know why he make the decision like this.
if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.


Incorrect -- arrays yield well-defined behaviour in C++.

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?


Your speech is unintelligible.

Here's some sample code:

#include <cstddef>
#include <cassert>
#include <iostream>

using std::cout;
using std::size_t;

#define restrict /* Nothing */
#define nullptr 0 /* Until next standard */

size_t const buflen = 64;

void PrintNullTerminatedArrayOfPointersToStrings(char const *const restrict
*restrict p)
{
assert(p);
assert(*p);

do cout << *p++ << '\n';
while(*p);
}

void PrintNullTerminatedArrayOfStrings(char const *restrict p)
{
assert(p);
assert(*p);

do cout << p << '\n';
while(*(p += buflen));
}

int main()
{
char const *const restrict names1[] = {
"Michael","John","Philip","Barry","Thomas",
"Luke","Owen","Richard","Keith",nullptr};

char const names2[][buflen] = {
"Michael","John","Philip","Barry","Thomas",
"Luke","Owen","Richard","Keith", {0} };

PrintNullTerminatedArrayOfPointersToStrings(names1);

PrintNullTerminatedArrayOfStrings(*names2);
}
Regards
-Wisdo
 
D

Daniel T.

Wisdo said:
Greg said:
char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to
use vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?
The problem is that you do not have an array of pointers, you
have an array or array's, so something like sex[1][2] has to get
to the right group of [128]'s. It's not sure what you want here,
but perhaps you want to pass each sex and accept a char *
instead.


Oops if not obvious "array or arrays" should say "array of arrays"


I want to know why C/C++ forbidden the covertion from char[][] to
char **p.

as many guys said, the char [12][12] and char ** are different
types, and of course can't covert into each other.

but in C/C++, the char [12] and char *p are the same expect the
latter lost the length information. i.e. in C/C++,

void f(char *p, int len); char s[7] = "array"; f(s, 7); <-- it's
OK.

but if we consider the same thing in two-dimenstion

void f(char **p, int with, int height); char s[2][128] = { "Male",
"Female" }; f(s, 2, 128); <-- this need auto-convertion from
char[2][128] to char** , but it's forbidden in C/C++.

I'm interesed in the regular design about C/C++ about this ban,
it's forbidden and what it want to avoid?


The question you want answered really should be asked in comp.std.c++. However, from what I know, the compiler can't make the conversion you
ask for because it doesn't keep track of the start location of each
start point for the second dimension.
 
A

Alf P. Steinbach

* Wisdo:
why char [10][10] and char ** are mismatch,
but char[10] and char * are not mismatch?

First, why this OK:

char a[10];
char* p = a; // OK

Here 'p' is initialized to point to first element of 'a'.

When you dereference 'p', the expression '*p', you have a reference to
the first element of 'a', and you can use that value or assign to it.

Now consider

typedef char* CharPointer;
CharPointer ahum[10];
char** pp = ahum; // OK

This is also OK. 'ahum' is an array of 10 char* pointers, and 'pp' is a
pointer to char*. 'pp' is initialized to point to the first element of
'ahum', which is a char* pointer just like all other elements of 'ahum'.

Finally consider

char argh[10][10];
char** pp = argh; // NOT OK.

'pp' is a pointer to char*, but is initialized to point to a char[10]
array (the first element of 'argh' is a char[10] array). So if you
store a char* pointer value in '*pp', you'll be storing a pointer value
in a 'char' or a number of 'char' values, depending on the size of a
pointer in that C++ implementation. Ordinarily that would be an error,
and C++ protects you against that by checking the types you use.
 
G

Greg Comeau

as many guys said, the char [12][12] and char ** are different types,
and of course can't covert into each other.

but in C/C++, the char [12] and char *p are the same expect the latter
lost the length information.

IOWs, they are not the same. There is in C and C++ what
can be considered an anomaly. In short, we can do this:

char c = 'x';
char a[] = "blah";
char *p;

and then both of these will work:

p = &c;
p = a;

Neither of these is probably surprising, but, it's easy to think
or say in the second case "p points to the array a". The "problem"
is that of course it is only pointing to the first character of a.
After all, p is declared as pointer to A char. A as in one.

The type of a is char[5]. In some (most) circumstances, it get
CONVERTED to a char *. This means information is indeed lost.

This is a problem, because we have the notion of incementing a pointer.
However, this is not a good idea:

p = &c;
p++; // Huh?

Nor even this:

char one[1] = { 'c' };
p = one;
p++; // Yikes!

IOWs, things such as bounds checking are not a requirement
upon an implementation or the code it generates.o

This happens at even level of indirection, but usually because
we normally stay in the level we're in the collapsing of the most
immediate dimension is seen as reasonable while those at others are not.

So, this would not seem reasonable:

char a2[4][5];

p = a2;

EVEN THOUGH, the programmer may have just wanted to travese
the 20 char for some reason. You can of course cast the assignment
to a char *, but then you're on your own, even more so than normal.
Not only do you loose the most immediate dimension but you loose both.
Normally that's too much lost and so normally becomes an error to
be allowed to happen implicitly. After all, you made it a 2d array
instead of a 1d array for some reason. So with a2 normally you'd
want to be dealing with each char[5] (a2[0], a2[1], a2[2], a2[3], a2[4]).
or each char (a2[x][y]) and not changing it into some other shape.
 
G

Greg Comeau

as many guys said, the char [12][12] and char ** are different types,
and of course can't covert into each other.

but in C/C++, the char [12] and char *p are the same expect the latter
lost the length information.

IOWs, they are not the same. There is in C and C++ what
can be considered an anomaly. In short, we can do this:

char c = 'x';
char a[] = "blah";
char *p;

and then both of these will work:

p = &c;
p = a;

Neither of these is probably surprising, but, it's easy to think
or say in the second case "p points to the array a". The "problem"
is that of course it is only pointing to the first character of a.
After all, p is declared as pointer to A char. A as in one.

The type of a is char[5]. In some (most) circumstances, it get
CONVERTED to a char *. This means information is indeed lost.

This is a problem, because we have the notion of incementing a pointer.
However, this is not a good idea:

p = &c;
p++; // Huh?

Nor even this:

char one[1] = { 'c' };
p = one;
p++; // Yikes!

IOWs, things such as bounds checking are not a requirement
upon an implementation or the code it generates.o

This happens at even level of indirection, but usually because
we normally stay in the level we're in the collapsing of the most
immediate dimension is seen as reasonable while those at others are not.

So, this would not seem reasonable:

char a2[4][5];

p = a2;

EVEN THOUGH, the programmer may have just wanted to travese
the 20 char for some reason. You can of course cast the assignment
to a char *, but then you're on your own, even more so than normal.
Not only do you loose the most immediate dimension but you loose both.
Normally that's too much lost and so normally becomes an error to
be allowed to happen implicitly. After all, you made it a 2d array
instead of a 1d array for some reason. So with a2 normally you'd
want to be dealing with each char[5] (a2[0], a2[1], a2[2], a2[3], a2[4]).
or each char (a2[x][y]) and not changing it into some other shape.

OOps, my examples used char * and not char ** but the gist of points
made should still hold.
 
J

Jim Langston

Wisdo said:
Greg Comeau дµÀ:
char [10][10] to char ** is compile error. why?

if i hava a string array. yes. it's not safe and it's better to use
vector<string> instead.

but my point is the language feature.

char sex[2][128] = {"Male", "Female" };

void print(char **p, int len) {
// print all sex
}

print(sex, 128); // <--- this cause compile error.

Is any issue to make the language forbiden this covertion?
The problem is that you do not have an array of pointers,
you have an array or array's, so something like sex[1][2]
has to get to the right group of [128]'s. It's not sure
what you want here, but perhaps you want to pass each
sex and accept a char * instead.


Oops if not obvious "array or arrays" should say "array of arrays"


I want to know why C/C++ forbidden the covertion from char[][] to char
**p.

as many guys said, the char [12][12] and char ** are different types,
and of course can't covert into each other.

but in C/C++, the char [12] and char *p are the same expect the latter
lost the length information.
i.e. in C/C++,

void f(char *p, int len);
char s[7] = "array";
f(s, 7); <-- it's OK.

but if we consider the same thing in two-dimenstion

void f(char **p, int with, int height);
char s[2][128] = { "Male", "Female" };
f(s, 2, 128); <-- this need auto-convertion from char[2][128] to char**
, but it's forbidden in C/C++.

I'm interesed in the regular design about C/C++ about this ban,
it's forbidden and what it want to avoid?


char MyArray[12][12];
MyArray is a pointer to 144 characters.

char** MyPArray;
MyPArray is a pointer to pointers.

You see the difference? Once points to characters, one points to ponters.
They are NOT the same.
MyArray[5][0] is a CHARACTER, not a pointer.
MyArray[5] is a pointer, but only by conversion.
 
G

Greg Comeau

char MyArray[12][12];
MyArray is a pointer to 144 characters.

You've overspoke :)

MyArray is a char[12][12] which is some cases is automatically
(implicitly) converted to a char (*)[12].
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,689
Members
48,796
Latest member
Greg L.

Latest Threads

Top