· int arr[4] 这个数组中,arr[4]的类型是整形,它表示这个数组中下标为4的元素(即第五个元素)
而arr则表示数组arr的首地址, arr的类型是:指向int(这里因为定义是int 如果定义成char,则是指向char,以此类推)的常量指针
· 大部分情况下,数组名arr都作为数组的首元素地址 只有两种情况例外
1.siziof(arr) :返回值为数组的长度
2.&arr :指向数组的指针 (和arr等价)
· 数组名arr是个常量,它不能被修改
例如 arr = 2 这样的表达式是非法的
· *(array + 3) 和array[3] 这两个访问方式,前者是间接访问,后者是下标引用,
这两种方式的作用完全相同,优先级不同
两种访问方式做比较:
可读性方面,下标访问有优势,但,贴一段话:
下标绝不会比指针更有效率,但指针有时会比下标更有效率
这里还有一篇博文,作者通过编程实例比较说明两种访问方式的效率差异
贴上来,有时间看看:
http://blog.sina.com.cn/s/blog_615ec1630102uxo1.html
(其实也都是这本书里的内容)
· 提高指针效率的方法
1、当你根据某个固定数目的增量在一个数组中移动时,使用指针变量将比使用下标产生效率更高的代码。当这个增量式1并且机器具有自动增量模型时,
这点表现得更为突出。
2、声明为寄存器变量的指针通常比位于静态内存和堆栈中的指针效率更高(具体提高的幅度取决于你所使用的机器)
3、如果你可以通过测试一些已经初始化并经过调整的内容来判断循环是否应该终止,那么你就不需要使用一个单独的计数器
4、那些必须在运行时求值的表达式往往代价更高
当然,在提高效率的同时,也要注意程序的可读性,两者间一定要合理取舍
· 声明一个数组,编译器根据你指定的元素数量在内存里开辟空间,所以声明的这个数组是个常量
而声明一个指针,编译器只为指针本身保留内存空间,因此它是一个变量
int a[5]; 这个表达式是合法的
int *b; 这个表达式是非法的
所以注意,在声明和定义一个指针变量的时候,一定要在定义的同时进行初始化
· 当一个数组名作为参数传递给一个函数,传递的是数组首地址
· 对一个函数,如果传入的参数是一个值,那么在这个函数中你可以对这个参数随意修改,并不会改变这个参数在主函数中的值
而如果传入的是一个地址(比如数组),函数中对它的修改则会影响主函数中它本身的值。
· 数组作为参数传递给函数:
int fun(char *p)
int fun(char p[])
第一种更准确,写代码的时候应该用第一种,如果需要知道数组的长度,应该再把长度也作为一个参数传递进来
· 字符数组的初始化:
char message = {‘H‘, ‘E‘, ‘L‘, ‘L‘, ‘O‘ ,0};
char message = {‘H‘, ‘E‘, ‘L‘, ‘L‘, ‘O‘ , ‘\0‘};
char message[] = "HELLO";
· 看这段代码:
int main()
{
char message1[] = "hello" ; //message1为一个数组,长度为6,内容为 h e l l o \0
char *message2 = "hello" ; //message2为一个指针 指向字符串常量 hello
printf( "1:%s\n", message1);
printf( "2:%s\n", message2);
return 0;
}
两个printf打印的结果都是hello 但message1、message2本质是不同的
message1是一个数组 message2是一个字符串常量
相应的,你可以对message1数组中的元素进行修改
而message2作为一个字符串常量,其内容是不能修改的
· 二维数组的下标、查找与指针
设有一个二维数组 arr[3][4]
*(*(arr + 2) + 3) 和 arr[2][3] 访问的是相同的元素。
· 指向二维数组的指针
int arr[3][10];
int (*p)[10] = arr;
使用 *(*p + i) 表示访问数组中的第i个元素。 比如i= 15 表示arr[1][4]
·