Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141409
  • 博文数量: 30
  • 博客积分: 887
  • 博客等级: 准尉
  • 技术积分: 342
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-03 19:11
文章分类

全部博文(30)

文章存档

2012年(19)

2011年(1)

2010年(6)

2009年(4)

我的朋友

分类: LINUX

2010-08-29 22:42:43

 
论坛上关于char (*p)[] 和char p[]的问题
char (*p)[]是定义一个指向char型数组的指针.
char p[]是定义一个数组,p也是指针,只不过是常量.对吧?
#include
int main()
{
        char (*p)[10] ;
        char a[10];
        p=a;
}
为什么提示
[root@localhost ~]# cc test.c
test.c: 在函数 ‘main’ 中:
test.c:6: 警告:从不兼容的指针类型赋值呢?

你把p=a 改成 p=&a就可以了。
这是c语言迷惑人的地方。很多书都告诉大家数组名就是数组的地址,但其实它是的数组第一个元素的地址,类型是char *。而&a 表示的才是数组的地址,类型是char (*)[10]。由于数组的地址在值上面和数组第一个元素地址的值是相同的,所以大家平时就认为&a和a是一样的,产生了误会。
所以,p=a的警告在于你把一个char型的地址赋给了一个char (*)[10]的指针。当然,这样做的结果没错,不过多了个警告。
发表于: 2006-10-13 12:37    主题:   [引用]  [投诉] [快速回复] 
 
--------------------------------------------------------------------------------
 
指向数组的指针 和 指针数组是不一样的
指向数组的指针char (*p)[10]表示p指的是一个数组,p+1与p的差距是sizeof(char [10]),是移动指到另一个数组,这里sizeof(p)在32位机器上应该是4,指针的长度是4
指针数组char *p[10],表示的是一个数组,数组中每个元素都是指针,这里sizeof(p)在32位机器上应该是40,=10 * sizeof(char*),这儿是数组的长度,而不是指针的长度,也说明他是个数组,跟指向指针的指针(char **p)也是不一样的
还不明白自己去看书了,不回复了
 

好像大家说得挺复杂的,这个问题,其实可以归纳为三个问题:
1、p是什么?
2、a是什么?
3、&a又是什么?
先看这个例子:
int *p;
int a[10];
p = a;
这里,p = a ,其实仅仅是指向了数组的下标为0的元素,它仅代表一个元素,而不是整个数组,你不能用指针p来描述整个a[10],除非你做一个循环。
好了,把最后一句 p = a改为:
p = &a;
p 仅仅是代表一个元素,而&a是整个数组的地址(&a实际上是指向数组a的指针),一个元素是不能指向整个数组的,因为它们类型不一致,编译器会警告!!!
(令人疑惑的是:虽然是警告,但又可以编译运行,这是因为&a使终表示一个地址,如0x0012ff70,而&a[0]也是一个地址,p = &a[0],那当然……,虽然可以运行,但是从类型上来讲,这样是不对的)
说了一大堆和楼主问题不相干的。其实好像已经回答了这个地址,楼主的程序中:
p是一个指针,是一个指向有10元素的数组的指针,——它已经代表了10个元素,不再代表一个元素了!!!
a,前面已经说了,a是下标为0的元素的地址——它仅代表了&a[0]
大家好像不在一个数量级别上吧?编译器当然要警告你,当然你也可以强行这么用,原因如前所述。
所以,要让大家在一个级别上,很简单,把最后一句
p = a;
改成
p = &a;
搞定!!!
后记:虽然a[10]中,a和&a,表示的绝对的地址的二进制数是相同的,比如0x001270FF,但是,它们代表的含义却不是一样的!!!
我举例用了int来代替楼主的char类型,主要是因为char常常让我们迷惑……之所以迷惑,是因为我们习惯于
char *p;
char a[10];
p=a;
/*以下把p看成一个字符串来用*/
事实上,C是没有字符串的类型的,p 之所以能看成字符串,因为p指向了第一个元素,我们可以使用它,直至'\0'
Over!
不对之处还请谅解!
 

两个指针级别都不一致,一个是char (*)[10], 一个是char [10],当然要警告你一下
char [10] 是数组 a 的定义类型,是数组类型,而不是指针类型。数组可以转换为指针,所以一个数组到底是作为数组类型还是指针类型使用取决于它所处的上下文环境。程序中的 p = a; 中 a 作为指针使用,此时它的类型是 char*。
>>(char p[] 中,)你这个p怎么能++的哦,这个p就是个常量,不是左值,不能对其进行赋值什么的操作
>> a是指针常量,不能作为左值,当然也是不能自增的了..
首先可以肯定的是:楼主程序中的数组 a 是一个非静态数组,所以 a 不是一个常量。
经常看到上面的这种错误的观点,即把改变数组名 a 的操作(如对其赋值、自加等)是非法的原因归结于“数组名是常量”。我在下面的帖子中对此进行了澄清:
... p;extra=&page=2
按照标准的说法,数组名 a 不能被改变是因为数组对象是一个“不能被改变的左值”。这句话表达了两个意思:一是数组对象是一个左值,二是不存在数组类型的赋值、自加、自减等操作。另外,数组对象 a 作为指针使用的时候,你可以说它是一个常量指针(这总是正确的),然而能否说成是一个指针常量(即地址常量)就又另当别论了(具体参见上面给出的帖子中的内容)。
>> 不过a里面存的不已经是数组第零个元素的地址,怎么还能&取址呢?
因为这个地址值是“转换”而来的,而不是存放在变量 a 中,这是数组类型一个比较特殊的地方。另外,能对数组 a 进行取址运算是因为 a 表示数组对象的时候是一个左值。
>> 难道&a和a内容一样,差别在于类型变了,一个是单个元素的指针,一个是数组的指针了么?
&a 和作为指针使用的 a 这两个表达式都只有“值”的概念,不代表任何对象,所以没有你所认为的“内容”。它们的值仅仅是在数值上相等(因为指向位置相同),然而指针类型不同:前者是 char(*)[10],后者是 char*。
 
#include
int main()
{
        char (*p)[10] ;
        char a[10];
        p=a; // First of all, "a" means &a[0],  p should be assigned with the address of an array, not the address of the array element.
        You should write as : p = &a;
}

/*----------------------------
看后写出如下程序,正确得到结果
----------------------------*/
#include
#include

int main()
{  
  
        char (*p)[10] ;
        char a[10];
       
        strcpy(a,"hello,world");
       
        p=&a;
       
        printf("p=%s\n "
       "the  second char in p  is %c\n",*p,(*p)[1]);
       
        return 0;
       
}
阅读(1109) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~