user-0 提问: 函数之间二维数组多种表示方法的传递问题

回复:
user: user-1
content: 引用 47 楼 xiaopo_poxiao 的回复:[quote=引用 42 楼 mujiok2003 的回复:] [quote=引用 41 楼 xiaopo_poxiao 的回复:] sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.[/quote] 哥们要分的话，开贴给你！[/quote]  不要.

user: user-0
content: 引用 46 楼 u013470052 的回复:[quote=引用 45 楼 xiaopo_poxiao 的回复:] [quote=引用 44 楼 u013470052 的回复:] [quote=引用 43 楼 xiaopo_poxiao 的回复:] 你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。[/quote] 好的，谢了哥们，还要分吗？要的话，可以开贴给你。[/quote] 不要  没意思[/quote]  我只是意思意思，哈哈。

user: user-0
content: 引用 42 楼 mujiok2003 的回复:[quote=引用 41 楼 xiaopo_poxiao 的回复:] sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.[/quote] 哥们要分的话，开贴给你！

user: user-2
content: 引用 45 楼 xiaopo_poxiao 的回复:[quote=引用 44 楼 u013470052 的回复:] [quote=引用 43 楼 xiaopo_poxiao 的回复:] 你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。[/quote] 好的，谢了哥们，还要分吗？要的话，可以开贴给你。[/quote] 不要  没意思

user: user-0
content: 引用 44 楼 u013470052 的回复:[quote=引用 43 楼 xiaopo_poxiao 的回复:] 你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。[/quote] 好的，谢了哥们，还要分吗？要的话，可以开贴给你。

user: user-2
content: 引用 43 楼 xiaopo_poxiao 的回复:你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。

user: user-0
content: szdata[ROWS][COLS] 传递给char *szdata[]是数组指针传递给指针数组 char *szdata[ROWS]传递给char *szdata[]就正常是因为都是指针数组   char szdata[ROWS][COLS]中，szdata也是一个数组指针，char *szdata[ROWS]中，szdata也是一个指针吧（不管说这个指针是不是数组指针）   二维数组 函数之间 传递实际是传递指针，那么这传过去应该没问题吧（当时这2个程序编译也都没问题，只是运行的时候有问题。）   也就是说在void print_alldata(char *szdata[], int rows) { for(int i = 0; i < rows; ++i) puts(szdata[i]); }这个函数内部执行的时候，运行有问题了，运行出现了崩溃。     而我如果不对szdata[i]操作的话，运行毫无问题（这是废话），操作了就会出现一个不正常，一个正常的问题。   那么，在char szdata[ROWS][COLS]中，每次执行，szdata[i]，也就是*(szdata+1)，szdata实际上每次会移动COLS个字符大小吧   那么，在char *szdata[ROWS]中，每次执行，szdata[i]，也就是*(szdata+1)，szdata实际上每次会移动的大小是不固定的，取决于szdata指向行的字符串长度,比如第一次移动的大小应该就是sizeof("this is the first line!")，这样才能指向第二行。   那么，实际上，我们从本质上面来看，这两个传递过来的指针（你刚刚也说了，我们传递的是指针，而不管这两个指针到底是不是数组指针，反正是指针。），都是没问题的吧？那为啥char szdata[ROWS][COLS]就有问题？而char *szdata[ROWS]没问题呢？我就想知道，这个地方，这是我想知道的，其他关于数组指针和指针数组的区别我知道的。   我是想从传递的实质上来看，但是从语法角度来看，你说的确实没问题，数组指针传递给了指针数组，这不合语法啊，一个指针（数组指针）怎么能传给数组（指针数组）呢，只有指针数组才能传递给指针数组，但是实际传递的不都是指针吗？他真能传递一个数组（指针数组）给数组（指针数组）吗？

user: user-0
content: 引用 42 楼 mujiok2003 的回复:[quote=引用 41 楼 xiaopo_poxiao 的回复:] sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.[/quote] 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？

user: user-1
content: 引用 41 楼 xiaopo_poxiao 的回复:sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.

user: user-0
content: sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。

user: user-0
content: 应该是这样，此贴终结。给分！

user: user-0
content: 引用 35 楼 u013470052 的回复:[quote=引用 34 楼 xiaopo_poxiao 的回复:] 哈哈，NB，你是转到**，又转回来(char *)[COLS]，哈哈。 还有，麻烦你看下mujiok2003用户说的对不对，从10L开始，谢了哥们。  szdata的类型应该是 char(*)[100]；因为数组名本身代表了首地址，至于char[2][100]这类型，是不存在的。&szdata的类型是char(*)[2][100]；至于char **p = szdata，这个直接赋值在gcc下也会有警告的，在vc之类的直接通不过。后面的野指针应该是没有问题的，我一开始也是这样想的，应该是这样，不然不会报段错误，我刚才还试了下只输出szdata[0]也是段错误，所以只有这种说法成立了。[/quote]我明白了，谢谢哥们，你看看我这么理解对不对？ char *szdata[ROWS]开辟了新的空间来正确的存储了两个字符串的地址，而char szdata[ROWS][COLS]把错误的地址赋值给了二级指针（就是野指针了），如果限制了维数（列）的大小，就能正常传递了。。。

user: user-2
content: 引用 36 楼 u013470052 的回复:其实上面说的不是针对本题说的，就是就题论题说的。 又说错了，是就这个复制问题而言

user: user-3
content: 擦，我讲得很清楚啦 一般的一维数组 char ct[10] = "test"; 内存里 t e s t 0 ... 所以弄个指针char *p = ct; 那么 *p == 't'; *(p+1) = 'e'; 所以一维数组和一维指针没啥两样 但对于二维数组 char ct[2][6] = {"test", "other"}; 内存里 t e s t \0 \0 o t h e r \0  int main() {     char test[2][10] = {"test", "other"};     typedef char Array[10];     Array *p = test;     std::cout << *p << std::endl; }  看上面这个例子，test对应得是Array的指针，而不是char *的指针，这就是你代码1的错误。 其实换种说法估计LZ可能会更好理解，数组作为参数传给函数，只能退化一级，也就是一维数组变成一维指针，二维数组变成指向一维数组的指针，但不能变成两维指针。因为数组变指针，只是丢失了数组长度的信息，但数组内容还是可以通过指针和整数的加法运算获得。而对两维数组，如果你变成了二维指针，那么数组内容就没办法通过指针和整数的加法获得了，因为对于 Array *p1 和 char **p2 p1 + 1 和p2 + 1根本不是一个东西 p1 + 1的地址应该是p1的地址加上sizeof(Array)，而p2的地址，是p2 + sizeof(char *)，显然是不同滴，而前者才是正确滴

user: user-2
content: 引用 24 楼 xiaopo_poxiao 的回复:[quote=引用 23 楼 u013470052 的回复:] 嗯嗯,我看了下. 你把二维数组也就是 存有两个字符串的地址赋值给了 指针数组了，而指针数组中存放的都是指针，这道题目中指针数组szdata使用了两个指针，也就是元素0和1,他们分别指向自己的区域，相当于两个独立的指针，0肯定不会出错，因为szdata[0]是指向了二维数组的首地址了，而szdata[1]是指向了哪里呢？指向了一个未知区域。属于未定义的行为。你要使用szdata[1]来输出，也就是读取你没有权限的内存肯定会段错误。其实这个行为本来就是不可取的，因为不兼容的类型间赋值本身就容易出问题。 你我看不明白你说的，你说的是代码几？2？2没问题，有问题的是1，我发现10L说的有道理了。。。。[/quote] 其实上面说的不是针对本题说的，就是就题论题说的。

user: user-2
content: 引用 34 楼 xiaopo_poxiao 的回复:哈哈，NB，你是转到**，又转回来(char *)[COLS]，哈哈。 还有，麻烦你看下mujiok2003用户说的对不对，从10L开始，谢了哥们。  szdata的类型应该是 char(*)[100]；因为数组名本身代表了首地址，至于char[2][100]这类型，是不存在的。&szdata的类型是char(*)[2][100]；至于char **p = szdata，这个直接赋值在gcc下也会有警告的，在vc之类的直接通不过。后面的野指针应该是没有问题的，我一开始也是这样想的，应该是这样，不然不会报段错误，我刚才还试了下只输出szdata[0]也是段错误，所以只有这种说法成立了。

user: user-0
content: 引用 33 楼 u013470052 的回复:#include <stdio.h> #define ROWS 2 #define COLS 100 void print_alldata(char *szdata[], int rows); int main(void ) {     char szdata[ROWS][COLS]={         "this is the first line!",         "this is the second line!"       };     print_alldata((char **)szdata, ROWS);      return 0; }  void print_alldata(char *szdata[], int rows) {      for(int i = 0; i < rows; ++i)         puts(((char (*)[COLS])szdata)[i]); } 运行正常。 哈哈，NB，你是转到**，又转回来(char *)[COLS]，哈哈。 还有，麻烦你看下mujiok2003用户说的对不对，从10L开始，谢了哥们。

user: user-2
content: #include <stdio.h> #define ROWS 2 #define COLS 100 void print_alldata(char *szdata[], int rows); int main(void ) {     char szdata[ROWS][COLS]={         "this is the first line!",         "this is the second line!"       };     print_alldata((char **)szdata, ROWS);      return 0; }  void print_alldata(char *szdata[], int rows) {      for(int i = 0; i < rows; ++i)         puts(((char (*)[COLS])szdata)[i]); } 运行正常。

user: user-0
content: 引用 30 楼 u013470052 的回复:我快疯了，哥们你continue。。。

user: user-0
content: 引用 28 楼 user-3 的回复: using namespace std;  int main() {     char test[2][10] = {"test", "other"};     cout << sizeof(test) << endl; //20     cout << sizeof(test[0]) << endl; //10     cout << sizeof(test[1]) << endl; //10 }  所谓二维数组，其实本质上还是1维数组。只不过是多个一维数组拼起来  using namespace std;  int main() {     char test[2][10] = {"test", "other"};     char **pp = (char **)test;     cout << (void *)test << endl;     cout << (void *)pp << endl;     cout << (void *)(*pp) << endl; }  输出 0x7fff66a37cd0 0x7fff66a37cd0 0x74736574 可以看到这里*pp已经是个很奇怪的指针了，对它的任何操作都很引起段错误~  int main() {     char test[2][10] = {"test", "other"};     char *p0 = test[0];     //char *p0 = (char *)test; //这个也可以     char *p1 = test[1];     cout << p0 << endl;     cout << p1 << endl; }  输出 test other  事实上test是指向一个长度为10的char数组的指针，而一般的char **pp是指向一个sizeof(char *)==4的指针，显然两者根本是不同的，至少test + 1一定不等于pp + 1 而char *p[10]是一个储存char指针的数组，和上面说的东西根本不是一回事。所以LZ的代码1显然是有问题的。至于代码2，LZ之间将szdata的类型给改了，使之和那个参数匹配，自然就没问题了，但szdata已经和char[][]没关系了~ 代码3是标准写法，代码4是将二维数组看出一维数组，事实上它本质就是个一维数组，所以也木有问题 朋友，麻烦你看下mujiok2003用户说的对不对，从10L开始，不是很明白你的意思。