数组名的值是一个指针常量(这个值不能被更改),其值为第一个数组元素的地址。它的类型取决于数据元素的类型:如果他们是Int 类型,那么数组类型名就是指向整型的常量指针。
但是这两种情况数组名并不用指针常量来表示。1、当数组作为sizeof操作符的或者单目运算&的操作数时。sizeof返回整个数组的长度,而不是指向数组指针的长度。&取一个数组名的地址产生的是一个指向数组的指针,而不是指向某个指针常量的指针。
int a[10], b[10], *c;
c = &a[0] 等价于 c = a;
b = a; 这是非法的,不能使用赋值符赋值数组元素
a = c; 非法,a是常量,不能更改。
a[3] 等价于 *(a + 3)
虽然可以互换的使用指针表达式和下标表达式,而且下标表达式简单明了,但是有时候指针表达式的效率可能高于下标表达式。
举个栗子:
使用指针快于下标情况。
/*
使用下标表达式给数组所有元素清0
为了对下标表达式求值,编译器会在程序中插入指令,每次取得a的值,然后与整形长度4相乘,确定数组元素的位置。
*/
int array[10], a;
for( a = 0; a < 10 ; a++ ) array[a] = 0;
/*
使用指针清零
虽然for循环调整部分ap++也存在乘法,1*4然后与指针相加。但由于是两个常量之间的乘法,所以编译器只需要在编译时执行一次。由于乘 法花费的时间对于cpu来说比较长 ,所以减小程序的大小和执行时间。
*/
int array[10], *ap;
for( ap = array; ap < array + 10; ap++ ) *ap = 0;
使用指针与数组效率相当的情况。
int array[10], a;
a = 10;
array[a] = 0; 等价于 *(array + a) = 0;
但是一般情况下,不会因为一点点效率差异而改用可读性差的代码!
声明一个数组时,编译器根据声明多指定的元素数量为数组保留内存空间,然后再创建数组名。声明指针变量,编译器只为指针预留空间。
int a[5]; int *b;
b++;
是合法的。但是a++;
不是合法的。
静态和自动初始化。
静态初始化在程序执行之前就已经初始化,如果静态数组没有初始化,那么自动赋值为0。自动变量的声明,每次执行流进入自动变量声明所在的作用域时,变量就被一条隐式的赋值语句初始化。对于数组的初始化,可能产生许多条赋值语句,初始化时间可能会非常“可观”。
/*
数组初始化举例
*/
int try[5] = { 1, 2, 3, 4, 5, 6 };//初始化值数量大于数组数组,这种声明是错误的。
int try[5] = { 1, 2, 3, 4 }; //正确,剩下未初始化的元素自动初始化为0.
int array[] = { 1, 2, 3};//自动计算数组长度;
char message[] = "hello"; //初始化一个字符数组
char *message2 = "hello"; //一个字符串常量,指针变量指向这个字符串常量的存储位置。
int a[3][6][10];
该数组是一个三维数组,它是一个包含三个元素的数组,每个元素又包含6个元素,而这六个元素又包含10个元素。
matrix[1][5]
等价于 *( *(maxtrix + 1) + 5 )
声明指向数组的指针:int maxtrix[3][10], (*p)[10] = maxtrix;
数组中每个元素值整数或者其他类型
区别指针数组:数组中每个元素是指向整形或者其它类型的指针。
注意: 如果要在指针上进行任何指针运算,避免这种声明方式 int (*p)[] = matrix;
数组长度不见了,进行指针运算长度调整时会乘上数组长度0。
/*
函数原型可以是一下两种任意一种。只要第二个及以后的各维长度才能对个小标进行求值,可以不知道第一维下标值。
*/
void func ( int (*mat)[10] );
void func ( int mat[][10] );
int matrix[3][10];
func( maxtrix );
//ps: 下面的声明是错误的 void func( int **mat );
//指向 整型指针 的指针 和 指向 整型数组 的的指针不是一回事。
例子:
/*
1、初始化一个2维数组
2、初始化一个3维数组
3、初始化一个4维数组
*/
int two_dim[3][5] = {
{ 00, 01, 02, 03, 04 },
{ 10, 11, 12, 13, 14 },
{ 20, 21, 22, 23, 24 }
};
int three_dim[2][3][2] = {
{
{ 000, 001 },
{ 010, 011 },
{ 020, 021 }
},
{
{ 100, 101 },
{ 110, 111 },
{ 120, 121 }
}
};
int four_dim[2][2][3][2] = {
{
{
{ 0000, 0001 },
{ 0010, 0011 },
{ 0020, 0021 }
},
{
{ 0100, 0101 },
{ 0110, 0111 },
{ 0120, 0121 }
}
},
{
{
{ 1000, 1001 },
{ 1010, 1011 },
{ 1020, 1021 }
},
{
{ 1100, 1101 },
{ 1110, 1111 },
{ 1120, 1121 }
}
}
};
注1: 如果用了花括号,那么每个子初始化列表都可以省略尾部的几个初始化值。
注2: 多维数组只能第一维可以省略下标值。
声明指针数组:int *api[10];
/*
判断参数是否与一个关键字列表中单词匹配,并返回索引值。未找到匹配则返回 -1;
*/
#include
char const *keyword[] = {
"do",
"for",
"if",
NULL
}
/*
也可以把关键字存在数组中。
char const keyword[][9] = {
"do",
"for",
"if"
}
*/
#define SIZE \
( sizeof( keyword ) / sizeof( keyword[0] ) )
int lookup_keyword( char const * const desired_word, char const *keyword[], int const size )
{
char const **kwp;
for( kep = keyword; *kwp != NULL; kwp++){
if( strcmp( desired_word, *kwp ) == 0 )
return kwp - keyword;
}
return -1;
}