LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: viper

C语言里面的指针和数组

[复制链接]
发表于 2003-7-1 12:07:35 | 显示全部楼层
可是,怎么能把他拉过来呢?
发表于 2004-12-12 08:48:40 | 显示全部楼层
只有领会了指针奥妙的人,才能真正掌握C语言。嗯哼!
发表于 2004-12-12 11:23:29 | 显示全部楼层
正常的编译器没有这种问题的,例如gcc 3.3,会直接报告 error: conflicting types for `int*a', previous declaration as `int a[2]'
发表于 2004-12-24 01:05:38 | 显示全部楼层
我的理解:
  所谓数组,就是把内存中的某块确定大小、地址、存贮类型的存贮空间给一个命名,数组名不能作为变量理解,你要把整个这样的存贮空间当成变量,对它的赋值实际上只能是给它的某个确定单元或整个存贮空间的每一个单元赋值,如:

  1. int a[10];
  2. for(int i=0;i<10;i++)a[i]=0;

  3. 或:
  4. int a[10];
  5. a[8]=0;

复制代码


而指针就是一个变量,它跟其它类型的如整形(int)、字符型(char)一样,可以赋值(条件是赋的值会被理解为地址)。现在假设你能确定0x8000开始的地址能被你访问而系统不会有意见,那么,下面代码:

  1. char* p;
  2. p=(char*)0x8000;
复制代码

就把地址0x8000赋值给了指针变量p;这跟

  1. int a;
  2. a=10;
复制代码

没有本质区别。上面(char*)0x8000;只是作了类型变换。

可是一般来说,我们用指针变量,来代表某一个地址,因此,很多人就把指针当地址,我不这么认为,应该说,指针变量的值是一个地址,看看下面代码:

  1. .
  2. .
  3. .
  4. char* p;
  5. p=(char*)malloc(64)
  6. printf("%X,%X",p,&p);
复制代码


它会打印两个什么值?p-打印的是malloc分配的地址的首地址,而&p-打印的是p这个变量占用的内存地址,这两个值绝对不会一样。也就是说,指针变量本身还占了一个地址,这跟其它变量是一样的,变量地址跟变量的值没有任何本质联系。我们再看数组:

  1. .
  2. .
  3. .
  4. int a[10];
  5. printf("%X,%X",a,&a);
复制代码

这个打印结果是两个值一样,都是数组a指示的首地址。也就是我开头讲的数组名不能作为变量理解,它只是个代名,不像变量,占有存贮空间。
c语言里,指针就是c语言的灵魂,用法不胜枚举,这里,就主题“C语言里面的指针和数组
”略述自已的一点见解,不当之处,还望指正。
发表于 2004-12-24 01:29:29 | 显示全部楼层
我这个菜菜也来说说,不对的地方大家请指正,共同提高嘛:
1.
a2 = a1; // ERROR, 数组不能赋值
我的看法是a1和a2既然是已经定义过的数组首地址,是常量了,不是指针一样的变量,当然不能再改动了,如果说成“数组不能赋值"比较难理解

2.void* p = 0;
p ++;

是可以编译过的。

编译通过了不能说明问题啊,因为指针变量的赋值是在运行阶段不是编译阶段,如果拿这个程序运行,很可能指针P指向的内存地址是受系统保护,不可访问的或只读不写的,运行就可能报错
发表于 2004-12-24 09:19:52 | 显示全部楼层
发表一点感慨。

我相信像gz12345这样的大牛是编程序编出来的。

我上大学的时候一个老师说过:在大学毕业之前要独立编写并调试成功一个一万行以上的程序(注意是一个程序,并且不包括VC,VB等工具自动生成的代码),才能达到一个计算机专业本科生的合格水平。很遗憾的是我没有达到,但我对他的话深信不疑。后来这位老师去美国研究人工智能了。(呵呵,如果他没走,我可能会在他的督促下完成这事了,不过这是马后炮了)。

学习编程最好的办法就是动手编,要想成为一个真正的程序员,“一个一万行的程序”只能算入门水平。
发表于 2004-12-24 09:41:37 | 显示全部楼层
我来凑合两句:
int const *p               //p是常数指针,只能指向一个int数,所指的内容可以变,但p不能变;
例如:
p=1234;
p=4321;
const int *p               //p指向常数int,常数不能变,但p可以变;
例如:
p=1234;
int *q=1234;             //反例怎么举?这里可能是错的!
const int const *p     //p和p指向的常数int都不能变;
p=1234;
p=4321                    //error
int (*prt)(datatype parameter)           //返回一个函数指针,因为每一个函数都有一个入口地址;
int (*prt[10])(datatype parameter)    //返回一个具有10个函数指针的函数指针数组,例子如何举?
int **p                                               //二级指针,p本身也有地址(有编译器决定),p的内容是一个
                                       //指针的地址
int volatitle *p                                    //p是一个int型指针,p有可能被修改
const int volatitle *p                          //p是一个int指针,p有可能被修改,但不能试图修改他
发表于 2004-12-24 09:47:17 | 显示全部楼层
4:   const与指针
  const是一个C语言的关键字,它限定一个变量不允许被改变。   如果const关键字不涉及到指针,我们很好理解,下面是涉及到指针的情况:
int b = 500;
const int* a = &b;             [1]
int const *a = &b;            [2]
Int* const a = &b;            [3]
const int* const a = &b;    [4]
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。
发表于 2004-12-24 16:20:18 | 显示全部楼层
我觉得数组和指针的争论实际上是C语言把我们误导了,数组不是指针,但在C语言中往往可以当作指针从?

比如
int arr[10];
int *a = &arr;

也可以写成
int *a = arr;

更直接一点:
printf("%d", arr); 和 printf("%d", &arr); 的结果居然是一样的

难道 arr 和 &arr 是一样的吗?!! 当然不是,把 sizeof(arr) 与 sizeof(&arr) 打出来看看,也许有助于理解它们为什么不一样。

有一种解释说:编译器对arr做了强行类型转换来支持这样的写法。可是通常意义上的强行转换却不是这样来做的,比如把 int 型变量 付给 指针型变量,与把 数组型变量 付给 指针型变量 的转换方法完全不同。

总之,C的这种性质在客观上对学习C语言的人造成了误导。
发表于 2004-12-24 18:30:42 | 显示全部楼层
这和C有什么关系。好好看书啊,C保证的是数组名保存了数组第一个元素的地址(这个显然和直觉的理解也吻合),从没有说国数组名是指针吧。看到地址就觉得是指针,只能说是缺乏逻辑的表现。
如果非说&arr,arr的值一样是造成误解的原因,n=&n, 得到的结果不也是一样,这样的例子多了,怎么没有觉得int也是指针呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表