为什么char aa[5][7]不能赋值给char **pp

slowgrace 2009-09-27 08:26:38
char aa[5][7];
char **ss;
char a[7];
char *s;

s = a; /*为什么这个可以*/
ss = aa; /*这个却不可以*/



s是一个指向字符的指针,a是一个有7个字符的数组,a[0]是a的第一个字符。s=a相当于s=a[0],就是让s指向a[0]的地址,这是可以的。也就是说,s可以等于a。

ss是一个指向字符指针的的指针,相当于ss是指向像s这样的指针的指针;
aa是一个有5个元素的数组,其中每个元素是1个有7个字符的数组,相当于aa含有5个像a这样的字符数组,aa[0]是其中第一个字符数组。
ss=aa相当于ss=aa[0],也就是让ss指向aa[0]的地址。

我纠结的是,既然s可以指向a,为啥ss不可以指向aa啊?

是不是因为ss是字符指针的指针,而aa[0]只能当做字符指针用啊?

二维数组char aa[5][7]的首地址是相当于字符指针还是相当于字符指针的指针呢?
...全文
1783 135 打赏 收藏 转发到动态 举报
写回复
用AI写文章
135 条回复
切换为时间正序
请发表友善的回复…
发表回复
ygtdxy 2012-05-16
  • 打赏
  • 举报
回复
正在学习指针和数组,压力。
wgxwgx 2009-11-26
  • 打赏
  • 举报
回复
学习了,呵呵。
zcgzdhxm 2009-10-23
  • 打赏
  • 举报
回复
学习了
雨青 2009-10-23
  • 打赏
  • 举报
回复
路过一下了
notax 2009-10-22
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 supermegaboy 的回复:]

6。按照C/C++的规则,我们可以:
    char *p1 = .......;
    const char *p2 = p1;
  但为什么const char **p2 = &p1;不行?


解决了以上几个问题,楼主对于数组与指针的理解,又会进入另一个境界了。
[/Quote]

gcc 也可以过
notax 2009-10-22
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 supermegaboy 的回复:]
4。在C中,有人说以下代码定义了一个常量:const int i = 10;但为什么如下代码不能通过编译?
    int main( void )
  {
        const int i = 10;
        int a[i];
        ..........
  }
[/Quote]

不对,gcc -std=c89 或 gcc -std=c99 可以过啊

ahao 2009-10-22
  • 打赏
  • 举报
回复
不错的帖子,不过我还是泼点冷水吧,如果主要用C++的话,裸指针都很少用,更不用说二级,多级指针了...
slowgrace 2009-10-22
  • 打赏
  • 举报
回复
准备结帖了。这个帖子在supermegaboy的引导下又延伸出很多问题,为此又看了不少东西,之后又得到很多指点,非常感谢supermegaboy。

也谢谢brookmil, cphj, hpsmouse, borefo,wangmu7206等许多朋友的热心回复和指点。

对我有启发的回复都给了分,以方便后来的朋友查看。

这个帖子的内容比较多,其中一部分小结在这个帖子里:http://topic.csdn.net/u/20091020/15/425ceedc-afff-4af1-a298-6466914c1d2d.html

其他的内容还在整理中,过一段会在论坛和博客中贴出来。
qiang81020 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 supermegaboy 的回复:]
呵呵,祝贺楼主和brookmill终于大彻大悟。

说到C/C++的复杂性,我常常听到有人说C++的类很复杂,但其实C++的类只是庞大,不是复杂,由于规则很多,外延反而变小,灵活性受到了约束;而指针由于规则少,只有那么一两条,灵活性与复杂性反而更大。我从没有听到或看到过有人害怕写类,但却时常见到有人因为指针而抓狂、恐惧,甚至出现了拒绝使用指针的思潮。

解决了复杂指针的阅读,还有很多内容等着楼主去思考,例如:

1。数组名是一个常量吗?

2。我们常这样使用:
    int a[10];
    int *p = a + 1;
  这是否意味着数组名是一个指针?

3。为什么a与&a的地址值相同?

4。在C中,有人说以下代码定义了一个常量:const int i = 10;但为什么如下代码不能通过编译?
    int main( void )
  {
        const int i = 10;
        int a[i];
        ..........
  }

5。const char ****const *****const **** const p,p是什么??

6。按照C/C++的规则,我们可以:
    char *p1 = .......;
    const char *p2 = p1;
  但为什么const char **p2 = &p1;不行?

7。我们常常使用这样的指针:const char *p1;但对于下面的声明:
    typedef char * T;
    const T p2;     
    p1与p2也一样吗??为什么?重点在于为什么??


解决了以上几个问题,楼主对于数组与指针的理解,又会进入另一个境界了。
[/Quote]

我去进入另一个境界了。。。。
赵4老师 2009-10-15
  • 打赏
  • 举报
回复
对指针的彻底理解个人认为一定要在调试窗口看一下对应的汇编程序
luoqi 2009-10-15
  • 打赏
  • 举报
回复
说得很清楚了,aa就是一个指针,!=二级指针(指针的指针).

char *p = aa;
//p[0] = aa[0][0];
//p[8] 相当于 aa[1][0];
//但不能p[1][0],因为p是一级指针.
flyerwing 2009-10-15
  • 打赏
  • 举报
回复
char *p[7];
corn107 2009-10-15
  • 打赏
  • 举报
回复
Mark~
wanght99 2009-10-14
  • 打赏
  • 举报
回复
aa不能赋给ss是类型不匹配,隐式转换只能把“数组”转换成“指针”,aa这个表达式返回的是一个“指向一个数组的指针”而不是“指向指针的指针”隐式转换不会转换下一维的。
C语言中实际没有二维数组,只是用“数组的数组”来模拟二维数组的效果,这么理解就会清晰些了。
slowgrace 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 99 楼 supermegaboy 的回复:]
我这是举个例子给你看看错把表达式中的数组名看作对象会发生什么事情啊。
[/Quote]

好像有点明白了。指针左值和指针右值的寻址方式不同。指针左值是间接寻址,指针右值是直接寻址,如果弄混了很麻烦的。
飞天御剑流 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 119 楼 slowgrace 的回复:]
引用 37 楼 supermegaboy 的回复:
1。数组名是一个常量吗?
--
不能说是。提示:数组名是一个不变的符号地址,但在C中,不变的量就是常量吗??
在C中,常量表达式必须是编译期的,运行期的不是常量表达式。因此一个自动数组的数组名不是常量表达式,静态数组的数组名才是一个常量表达式。所以说,数组名只是一个符号地址,是否常量不一定,要视其如何定义的。
但在C++中,由于不再规定常量表达式必须是编译期,因此在C++中,数组名才是一个符号地址常量。


你这个问题,其实也是讨论数组名被隐式转换为指针右值时,“相当于”一个符号地址常量,是吧?而在&和sizeof之后,数组名其实是代表数组对象的,不会“相当于”一个符号地址常量。是吧?

[/Quote]

在作为&和sizeof的操作数时,数组名不是符号地址,当然也不是数组的首地址。

但转换后,数组名不一定是常量。
飞天御剑流 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 118 楼 slowgrace 的回复:]
只不过数组是一种特殊的对象.

普通的对象比如int i,我可以直接通过i这个变量名来存取它的值,比如i=1;

而数组是一种集合,不提供对集合整体的操作(除&和sizeof外),只提供对它单个元素的存取。而对它的单个元素的存取只用数组名(也就是变量名)就不足够了,必须还得加上下标。

这就是数组和普通对象的不同所在。
[/Quote]

没错。普通对象与数组体现的是两种不同的抽象方法,但目的都是一样的,都为了更容易地操作内存。
飞天御剑流 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 117 楼 slowgrace 的回复:]
引用 37 楼 supermegaboy 的回复:
3。为什么a与&a的地址值相同?
--------------------------------------------
这只是表面现象,有没有思考过&a是否合法?一般来说,&运算符要求操作数是对象,但,数组名是对象吗?
先给你解释什么是对象,对象是执行环境中其内容表示为某个值的存储数据的区域。

----------------------------------------------------------------------
如果定义int i; i是一个对象,&i成立是很自然的,但数组名不是对象(数组是对象),因为内存中并不存在一个地方存储数组名的值,数组名本身就代表一个值,没有指针对象那样的取值操作,因此按照&的本意,&a是非法的,但是由于早期有些编译器已经允许了&a这样的东西的存在,因此C标准委员会鉴于这种结构并没有害处而且对象的概念已经有了扩展,因此也规定了&a的合法性,但&a并不表示对数组名取地址,而是对数组对象取地址,也正因为这个原因,&a的值跟a是一样的


你这里说的“数组名不是对象”,其实是说数组名出现在普通表达式中被隐私地转换为了指针右值,是吧?你强调这一点,其实是为了让我了解数组名的指针右值特性,是吧?

其实,我们也完全可以认为,数组名在&和sizeof之后就代表数组对象,是吧?
[/Quote]

没错。作为&和sizeof的操作数时,不进行数组到指针的转换,数组名此时就代表数组对象。

我之所以提到&a的合法性,是由于&被该条款作为例外之一,如果没有这个例外,a被转换成一个右值,对其取地址就是非法的,但C标准委员会鉴于对象概念已经有所发展,因此允许了&a的合法性。标准在rationale中阐述了这一原理:

6.5.3.2 Address and indirection operators

Some implementations have not allowed the & operator to be applied to an array or a function. (The construct was permitted in early versions of C, then later made optional.) The C89 Language Committee endorsed the construct since it is unambiguous, and since data abstraction is enhanced by allowing the important & operator to apply uniformly to any addressable entity.
  • 打赏
  • 举报
回复
数组名不等于指针
slowgrace 2009-10-11
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 supermegaboy 的回复:]
1。数组名是一个常量吗?
--
不能说是。提示:数组名是一个不变的符号地址,但在C中,不变的量就是常量吗??
在C中,常量表达式必须是编译期的,运行期的不是常量表达式。因此一个自动数组的数组名不是常量表达式,静态数组的数组名才是一个常量表达式。所以说,数组名只是一个符号地址,是否常量不一定,要视其如何定义的。
但在C++中,由于不再规定常量表达式必须是编译期,因此在C++中,数组名才是一个符号地址常量。
[/Quote]

你这个问题,其实也是讨论数组名被隐式转换为指针右值时,“相当于”一个符号地址常量,是吧?而在&和sizeof之后,数组名其实是代表数组对象的,不会“相当于”一个符号地址常量。是吧?
加载更多回复(116)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧