C 语言 指针问题

2017-01-30 20:02:08 +08:00
 cio
#include <stdio.h>

const int MAX = 3;

int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;

   /* 指针中的数组地址 */
   ptr = var;
   for ( i = 0; i < MAX; i++)
   {

      printf("存储地址: var[%d] = %x\n", i, ptr );
      printf("存储值: var[%d] = %d\n", i, *ptr );

      /* 移动到下一个位置 */
      ptr++;
   }
   return 0;
}

其中的 ptr = var; 这里是把数组 var 的第一个值得地址赋值给了 ptr 指针吗? 那可不可以这样写 ptr = &var[0];

刚学。可能问的问题弱智了点,还是期望有人解惑..

3372 次点击
所在节点    C
31 条回复
ryd994
2017-01-31 12:56:15 +08:00
@introom 考虑这 short *a=1; long *b=2
ryd994
2017-01-31 12:59:55 +08:00
@zhujinliang 只要指针类型对,指针加减的偏移量是正确的
指针加加减减是很正规的用法
C 规范规定了 a[i]和*(a+i) 是等同的
introom
2017-01-31 14:42:54 +08:00
@ryd994 之前楼上那位的意思应该是说,比如
int arr = {1,2,3}
那么, arr[1]和 1[arr]一个意思。

你的问句是,如果 a,b 不是一个类型呢?
所以 a,b 是一个类型是什么意思?
crazyjin
2017-01-31 15:40:01 +08:00
楼主去看看《 csapp 》的前几章,再看看《 c 陷阱与缺陷》。你会理解 c 的指针的本质,并且见识一些极端复杂的用法。
snnn
2017-01-31 18:42:44 +08:00
@zhujinliang “我觉得&a[n]写法更好,因为 a 的类型不确定,用数组的形式编译器会自动决定偏移多少”

C 语言中所有类型都是静态的。不存在不确定的类型。
snnn
2017-01-31 18:43:22 +08:00
@ryd994 “考虑这 short *a=1; long *b=2 ”

你这代码编译不过去。
mintist
2017-02-01 15:00:22 +08:00
C 语言中的 **指针** 由两部分构成:地址值和类型。

地址值就是数字,和汇编中是一样的。

而类型,在汇编里面是没有的,所以是给 C 语言的编译器看的,在编译期间, C 语言会根据你写的指针类型给它们分配所需要的空间。
(或者说是弱类型吧,不能说没有类型,而是只有简单的不同位数的整形,浮点型,而没有指针,数组,数组的数组之类的高阶的类型,因为汇编器是比较原始的,没有那么复杂的设计)

再回到题主的问题:

“ ptr = var; 这里是把数组 var 的第一个值得地址赋值给了 ptr 指针吗? 那可不可以这样写 ptr = &var[0];”

这里有两个变量和类型:

ptr ,它的类型是 int *,为指向整形的指针;
var ,它的类型是 int [3],为有 3 个整形元素的数组。
var[0],它的类型是 int ,是*(var+0)的语法糖,所以自然也可以写成*(0+var),进一步的写成 0[var]。
而 & 表示取地址符的意思,所以 &var[0] 的类型是 int *。

所以,后两者只是地址值是相等的,其类型是不同的。

那么类型不同体现在什么地方呢?比如 sizeof(var) = 3*4 =12;而 sizeof(var) = 4 (假设为 32 位的机子)

当然,还有一些场景,两者会相互转换,比如函数传参数,数组会退化成指针,楼主用 “ C language array & pointer difference ”搜索下估计就能搜到不少

清楚了类型之后,可以看到,后者的写法是更加正确的,因为左右的类型都是 int *,而前者的写法左右两边类型是不同,有一个类型自动转化在里面,就是地址值过去了,类型给忽略掉了。
mintist
2017-02-01 15:02:25 +08:00
所以,一般个人在写的时候,会把 ptr = var;改成 ptr = (int*)var;,虽然必要性不大,但是这样写只是为了告诉自己,后面就用 int * 类型的指针去访问这段内存吧,的意思
visionsmile
2017-02-02 20:31:02 +08:00
@424778940 @lzhCoooder 数组名不是指针,标准里面是这么写的: Here x is a 3 × 5 array of integers. When x appears in an expression, it is converted to a pointer to (the first of three) five-membered arrays of integers. In the expression x[i] which is equivalent to *(x+i), x is first converted to a pointer as described; then x+i is converted to the type of x, which involves multiplying i by the length of the object to which the pointer points,namely five integer objects.
lzhCoooder
2017-02-03 10:41:42 +08:00
@visionsmile 数组名当然不是指针,我没说是指针呀...稍微写过一点就知道 sizeof 一个数组和一个指针结果是很不一样的,你搬出标准也只能证明数组名会被隐式转换成数组首地址,这我说的没错呀,一般用起来数组名就是代表首地址...
visionsmile
2017-02-03 12:43:22 +08:00
@lzhCoooder “你搬出标准也只能证明数组名会被隐式转换成数组首地址”,那不然还证明啥?“一般用起来数组名就是代表首地址...”,你这样说理解起来会有很大歧义....因为它并不“代表”首地址,只是在使用时会转换为指针。措辞还是要严谨一些啊。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/337435

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX