您的位置:首页 > 编程语言 > C语言/C++

C语言——数组知识大汇总

2015-08-17 10:11 375 查看
1、 定义

数组: 相同类型数据项的集合。

下标变量: 后面跟一个方括号内的下标的变量,指示一个数组元素。

数组下标: 在数组名后的方括号内的数值或表达式,用于指示访问哪个数组元素。

数组是由 ”类型名“ ”标识符“ ”维数“ 组成的复合型数据类型。

”维数“ 表示数组中包含的元素个数,必须大于等于 1 的常量表达式。此表达式只能包含 ”整型字面常量“ ”枚举常量“ ”用常量表达式初始化的整型const对象“。

2、 声明、初始化

语法: 元素类型aname[size]; 未初始化

[b]元素类型aname[size] = { 初始化列表 }; 初始化[/b]

a、静态和自动初始化

存储于静态内存的数组只初始化一次,因此当程序执行时,静态数组已经初始化完毕。

对于自动变量的初始化过程就没有那么浪漫啦,因为自动变量位于运行时堆栈中,执行流每次进入它们所在的代码块时,这类变量每次所处的内存位置可能并不相同。在程序开始之前,编译器没有办法对这些位置进行初始化。如果定义的数组比较大,那么每次初始化的时间是非常可观的。 所以就需要综合考虑是不是要声明为 static 。

b、不完整的初始化

c、自动计算数组长度:根据初始值的长度确定

d、字符数组的初始化

比较笨拙的方法: charmessage[ ] = { ‘H', ’e‘, ’l‘,’l‘,’o‘ };

快速初始化字符数组: char
message[ ] = ”Hello“;尽管它看上去是一个字符串常量,实际上不是。

区分字符数组与字符串常量

如: char
message1[ ] = "Hello";

char
*message2 = "Hello";

前者初始化一个字符数组的元素,而后者则是一个真正的字符串常量。这个指针变量被初始化为指向这个字符串常量的存储位置。

数组的集中初始化方式如下:

int a[3] = { 1, 2,3 };

int a[3] = { 1, 2 };

int a[ ] = { 1, 2,3 };

int a[3] = { [1] = 1, [ 0 ] = 2 }; (知道此种初始化方法即可)

使用循环顺序存取:

int square[10], i;

for (i = 0; i < 10; i++)

{

scanf("%d", &square[i]);

}

初始化一个三维数组:



3、 下标引用

下标引用实际执行的就是间接访问。

[b]一维数组:

[/b]

int b[10];



*(b + 3)这个表达式的意思是:首先 b 的值是一个指向整型的指针,所以 3 这个值根据整型值的长度进行调整。加法运算的结果是另一个指向整型的指针,它所指向的是数组第 1 个元素向后移 3 个整数长度的位置。然后,间接访问这个新位置,或者取得那里的值(右值),或者把一个新值存储于该处(左值)。

除了优先级之外,下标引用和间接访问完全相同。

例如下面两个表达是相同的:

array[ subscript ]

*( array + ( subscript ))

下面涉及 ap 的表达式中,写出使用array 的对等表达式

int array[ 10 ];

int *ap = array + 2;

ap array + 2&array[ 2 ]

*ap *(array + 2)array[ 2 ]

ap[ 0 ] 这个表达式对等的表达式是*(ap + (0)),除去括号,与上面的一样。

ap + 6 array + 8&array[ 8 ]

*ap + 6 这里有两个操作符,有优先级,* 的优先级大于 + ,所以对等表达应该为array[ 2 ] + 6

*(ap + 6) array[ 8 ]

ap[ 6 ] array[ 8 ]

&ap 这个表达式是完全合法的,但此时并没有对等的array 的表达式,因为你无法预测编译器会把ap 放在相对于array的什么位置

ap[ -1 ] array[ 1 ]

ap[ 9 ]
array[ 11 ] 超过数组的右边界,非法

[b]多维数组:

[/b]

int matrix[ 3 ][ 10 ]



matrix 它的类型是” 指向包含 10 个整型元素的数组的指针”,它的值是:



matrix + 1 它的类型也是” 指向包含 10 个整型元素的数组的指针”,它指向matrix的另一行:



*( matrix + 1)它的类型是“指向整型的指针”,是其中某个值的指针(即某个值的地址),等效于matrix[ 1 ]



*( matrix + 1)+ 5 它指向的位置比原先那个表达式所指向的位置向后移动了5个整型元素。



*(*( matrix + 1)+ 5 ) 对上面的值进行间接访问,取出这个元素(右值),如果作为左值则是存储一个新值。等效于matrix[ 1 ][ 5 ]

4、数组和指针

区别:

声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的是一个常量,指向这段空间的起始地址。

声明一个指针变量时,编译器只为指针本身保留内存空间,他并不为任何整型值分配内存空间。而且,指针变量并未初始化为指向任何现有的内存空间,如果它是一个自动变量,它甚至根本不会被初始化。

int a[ 5 ];

int *b;

表达式 *a 是完全合法的,但表达式 *b 却是非法的。 *b 将访问内存中某个不确定的位置,或者导致程序终止。

5、多维数组

如果某个数组的维数不止一个,它就被称为多维数组。

int c[ 6 ] [ 10 ];

把 c 看作是一个包含 6 个元素的向量,只不过它的每个元素本身是一个包含 10 个整型元素的向量。换句话说,c 是一个一维数组的一维数组。

存储顺序:

int array[ 3 ][ 6 ]



6、数组名

一维数组名:它的类型是”指向元素类型的指针“,它指向数组的第一个元素

考虑下面这些声明:

int a;

int b[10];

我们把变量 a 称为标量,因为它是个单一的值,这个变量的类型是一个整数。

我们把变量 b 称为数组,因为它是一些值的集合。

b[4] 的类型是整型,但 b 的类型是什么呢?

在C中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第一个元素的地址。

只有在两种场合下,数组名并不用指针常量来表示——就是当数组名作为 sizeof 操作符或单目操作符 & 的操作数时。

sizeof 返回整个数组的长度,而不是指向数组的指针长度。

取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量值的指针。

多维数组名:

多维数组的数组名与一维数组的差不多,唯一的区别是多维数组第 1 维的元素实际上是另一个数组。

如: int
matrix[ 3 ][ 10 ]

创建了 matrix ,它可以看作是一个一维数组,包含三个元素,指示每个元素恰好是包含 10 个整型元素的数组。

matrix 这个名字的值是一个指向它第一个元素的的指针,所以matrix 是一个指向一个包含10 个整型元素的数组的指针。

7、指向数组的指针、指针数组

首先它是一个指针,它指向一个数组。在32位系统下永远是占4个字节,至于它指向的数组占多少字节并不知道。它是“指向数组的指针”的简称;

下面来考考到底哪个是数组指针 、哪个是指针数组?

(A)int *p1[10];

(B)int (*p2)[10];

分析:首先我们要明白优先级的问题:

(A)“[ ] ”的优先级比“ * ”要高,p1先与“[ ]”结合,构成了一个数组的定义,数组名为p1,int *修饰的是数组的内容,即数组的每个元素。这个数组,其包含了10个指向int类型的数据指针,即指针数组;

(B)“()”的优先级高于“[ ]”,“*”与p2构成了一个指针的定义,指针的变量名为p2, int 修饰的是数组的内容,即数组的每天元素。数组这里并没有名字,是个匿名数组。现在我们清楚p2是一个指针,它指向一个包含10个int 类型的数据数组,即数组指针。

char (*)[10] p3; //也是数组指针。char (*)[10]是指针类型,p3是指针变量名。

8、作为函数参数的数组名、声明数组参数

作为函数参数的数组名:当一个数组名作为参数传递给一个函数时会发生什么情况呢?数组名的值是一个指向指向数组第一个元素的指针,所以此时传递给函数的是一份该指针的拷贝。

函数如果执行了下标引用,实际上是对这个指针执行间接访问操作,并且通过这种间接访问,函数可以访问和修改调用程序的数组元素。

所有的参数传递都是通过传值方式传递的。当然如果你传递了一个指向某个变量的指针,而函数对该指针执行了间接访问操作,那么函数就可以修改那个变量。尽管看上去并不明显,但数组名作为参数时所发生的正是这种情况。这个参数(指针)实际上是通过传值方式传递的,函数得到的是该指针的一份拷贝,它可以被修改,但调用程序所传递的实参不影响。

声明数组参数:

两个原型相等的函数:

一维情况:int strlen(char*string);
= intstrlen(char
string[ ]);(注意使用的上下文环境)

多维情况:void func2(int(*mat)[ 10 ]);
= voidfunc2(int
mat[ ][ 10 ]);

9、[b]数组的搜索与排序[/b]

数组搜索:






#define NOT_FOUND-1

int search( constint arr[],
inttarget,
intn)

{

int i, found = 0, where;

i = 0;

while(!found && i < n)

{

if(arr[ i ] == target)

found = 1;

else

++i;

}

if(found)

where = i;

else

where = NOT_FOUND;

return (where);

}

数组的排序:



int get _min_range(int
list[], int first, int last);

void select_sort(int list[] , int n)

{

int fill,
/* first element in unsorted subarray */

temp,
/* temporary storage */

index_of_min;/* subscript of next smallest element */

for( fill = 0; fill < n - 1; ++fill )

{

index_of_min = get _min_range(list, fill, n-1);

if( fill != index_of_min)

{

temp = list[index_of_min];

list[index_of_min] = list[fill];

list[fill] = list[index_of_min];

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: