C语言进阶8-数组

8.1 一维数组

8.1.1 数组名

数组名的值是一个指针常量(这个值不能被更改),其值为第一个数组元素的地址。它的类型取决于数据元素的类型:如果他们是Int 类型,那么数组类型名就是指向整型的常量指针。

但是这两种情况数组名并不用指针常量来表示。1、当数组作为sizeof操作符的或者单目运算&的操作数时。sizeof返回整个数组的长度,而不是指向数组指针的长度。&取一个数组名的地址产生的是一个指向数组的指针,而不是指向某个指针常量的指针。

int a[10], b[10], *c;

c = &a[0] 等价于 c = a;

b = a; 这是非法的,不能使用赋值符赋值数组元素

a = c; 非法,a是常量,不能更改。
    
a[3] 等价于 *(a + 3)

8.1.2 指针的效率

虽然可以互换的使用指针表达式和下标表达式,而且下标表达式简单明了,但是有时候指针表达式的效率可能高于下标表达式。

举个栗子:

使用指针快于下标情况。
/*
	使用下标表达式给数组所有元素清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;

但是一般情况下,不会因为一点点效率差异而改用可读性差的代码!

8.1.3 指针和数组

声明一个数组时,编译器根据声明多指定的元素数量为数组保留内存空间,然后再创建数组名。声明指针变量,编译器只为指针预留空间。

int a[5]; int *b;

b++; 是合法的。但是a++;不是合法的。

8.1.4 初始化

静态和自动初始化。

静态初始化在程序执行之前就已经初始化,如果静态数组没有初始化,那么自动赋值为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"; //一个字符串常量,指针变量指向这个字符串常量的存储位置。

8.2 多维数组

int a[3][6][10]; 该数组是一个三维数组,它是一个包含三个元素的数组,每个元素又包含6个元素,而这六个元素又包含10个元素。

matrix[1][5] 等价于 *( *(maxtrix + 1) + 5 )

8.2.1 指向数组的指针

声明指向数组的指针int maxtrix[3][10], (*p)[10] = maxtrix; 数组中每个元素值整数或者其他类型

区别指针数组:数组中每个元素是指向整形或者其它类型的指针

注意: 如果要在指针上进行任何指针运算,避免这种声明方式 int (*p)[] = matrix; 数组长度不见了,进行指针运算长度调整时会乘上数组长度0。

8.2.2 作为函数参数的多维数组

/*
	函数原型可以是一下两种任意一种。只要第二个及以后的各维长度才能对个小标进行求值,可以不知道第一维下标值。
*/
void func ( int (*mat)[10] );
void func ( int mat[][10] );

int matrix[3][10];
func( maxtrix );

//ps: 下面的声明是错误的 void func( int **mat );
//指向 整型指针 的指针 和 指向 整型数组 的的指针不是一回事。

8.2.3 初始化多维数组

例子:

/*
	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: 多维数组只能第一维可以省略下标值。

8.3 指针数组

声明指针数组: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;
}

你可能感兴趣的:(C语言,c语言,数据结构,开发语言)