Head First C 学习之指针和数组的区别

有必要学一学思维导图了,思维真的有些僵化,自建的记忆思维导图:

数组和指针记忆导图.jpg


数组与指针:

· 数组变量可以被用着指针
· 数组变量指向数组中第一个元素
· 如果函数参数声明为数组,他会被当做指针处理
· sizeof不是一个函数,而是运算符,编译器回把运算符编译为一串指令,所以程序实在编译期间计算出存储空间的大小的;而程序调用函数时,会调到另一段独立的代码中执行。


数组与指针又是完全不同的

    char s[] = "How big is it";
    char *t = s;
  • 1 sizeof(数组)是数组的大小而sizeof(指针)返回是4或8。

  • 2 数组的地址··· ···是数组的地址。

    指针变量是一个用来存储存储器地址的变量,如果堆数组变量使用&运算符,结果是数组本身。

    &s == s   
    &t != t

当程序员写下&s时, 表示“数组s的地址是”数组s的地址就是……s; 但 如果他写的是&t, 则 表示==变量t的地址是?==”。

自我理解:
&t表示指针变量t的存储地址,因为计算机回味指针变量分配存储空间.
t表示指针变量指向数据的存储地址。
所以 &t != t 
而计算机不会为数组变量分配任何空间,仅在出现它的地方把它换成数组的起始地址。
所以 &s == s
  • 3 数组变量不能指向其他地方
    当创建指针变量是,计算机会为它分配48字节的存储空间如果创建的是数组,计算机会为数组分配空间,但不会为数组变量分配任何空间,编译器仅在出现它的地方把替换成数组的起始地址
    由于计算机没有为数组变量分配空间,也就不能把它指向其他地方。
    s = t; 会编译报错
    但是 t = s 是可以的

指针退化

由于数组变量指针变量有一点小小的区别, 所以把数组 赋给 指针 时千万要小心。 假如把 数组赋给指针变量,指针变量只会包含数组的地址 信息, 而对数组的长度一无所知, 相当于指针丢失了一些信息。 我们把这种信息的丢失称为去退化
只要把数组传递给函数,数组就免不了退化为指针,但要记清楚代码中有哪些地方发生过数组退哈,因为他们会会引发一些不易察觉的错误。


为什么数组从零开始

数组变量可以用作指针,这个指针指向数组的第一个元素,也就是说除了方括号表示法,还可以用*运算符读取数组的第一个元素,如:

int drinks[] = {4,2,3};
printf("第一单:%i 杯\n",drinks[0]);
printf("第一单:%i 杯\n",*drinks);

两行代码是等价的,也就是说drinks[0] =*drinks

地址只是一个数字,所以可以进行指针算术运算,比如为了找到存储器的下一个地址,可以增加指针的值,也可以增加方括号的索引值:

int drinks[] = {4,2,3};
printf("第一单:%i 杯\n",drinks[2]);
printf("第一单:%i 杯\n",*(drinks+2));

表达式drinks[i]*(drinks+i)是等价的。
这也解释了为什么数组要从索引0开始
所谓索引,其实就是为了找到元素的地址,指针需要加上的那个数字。


为什么指针有类型

如果对char指针加1,指针会指向下一个地址,因为char就占1个字节。
如果对int指针加1,因为int通常占4个字节,因此编译后的代码就会对存储器地址加4
所以,指针之所以有类型,是应为编译器在指针运算是需要知道加几。


发表评论