1、简单的思考
看如下代码:
int array[5];
int matrix[2][3];
int* pa=array;
int* pb=matrix;
思考问题:
都知道,一位数组名array代表数组首元素地址,那么二维数组名matrix代表什么?也是首元素地址么?
array和&array的值相同,它们的意义不同,表现在它们的指针运算方式不同,为什么会有不同?指向它们的指针类型相同吗?
要回答第一个问题,必须要简单回顾一下二维数组;
1.1 二维数组:
定义方式:
类型说明符 数组名[常量表达式][常量表达式];
例如:int matrix[2][3];表示定义了一个2行3列存放整型数据的数组;
C语言中对二维数组采用这种定义方式,使得二维数组可被看作是一种特殊的一维数组,即是这个一维数组的每一个元素又是一个一维数组;
如下int matrix[2][3]的图解:
首先把matrix看作一个一维数组,它有两个元素:matrix[0],matrix[1];
每个元素又是一个包含3个元素的一维数组:
存储方式:
C语言中,二维数组中的元素排列顺序是按行存放的,即在内存中先顺序存放第一行的元素,接着再存放第二行的元素。
1.2 回答第一个问题
从二维数组的角度看,matrix确实也代表二维数组首元素的地址,而现在首元素的地址不是一个简单的整型元素,而是由3个整型元素所组成的一维数组;因此,matrix代表的是首行元素的首地址,它是首行3个元素所在内存这一整体的首地址,虽然在值上和matrix[0][0]元素的地址相同,但是意义不同;如果此时matrix+1,则表示matrix第1行元素的首地址;
1.3 与二维数组名相关的指针
1.4 数组类型的简述
C语言中,数组有自己特定的类型,这个类型由元素类型和数组大小共同决定;
例如:int array[5]的类型为int[5]
1.5 回答第二个问题
实际上本质的原因是array与&array所属的指针类型不一样,array属于int*类型因为它是数组首元素地址,&array属于int (*)[5],因为它指向数组,而数组的类型为int[5]
例如编译如下的代码,会得到注释中的警告信息
#include <stdio.h>
int main()
{
int array[5];
int (*pa)[5];
pa=&array;
int* pI=array;
int* p=&array;//这里会生成警告,初始化的指针类型不相同
return 0;
}
2、重命名数组类型
1.4中简单介绍了数组类型,这个类型写起来还是有点别扭,通常用typedef为其重命名:
typedef arrayType(NewName)[size];
如:typedef int(INT5)[5];
然后就可以使用它定义数组了:
INT5 a;
3、数组指针
数组指针用于指向一个数组;
数组名是数组首元素地址,不是数组的起始地址,虽然它们值相同!
通过将取地址符&作用于数组名可以得到数组的起始地址;
可通过重命名的数组类型定义数组指针:
typedef int(INT5)[5]; INT5 array; INT5* pa=&array;
也可以直接定义:type (*pointer)[n];
如:
int array[5]; int (*pa)[5]; pa=&array;
4、指针数组
指针数组也算是一个普通的数组,只不过数组中每个元素为一个指针;
指针数组的定义:
type * pArray[n];
例如:int* p[5];//数组中将存放5个int*型的地址
5、指针数组的使用
#include <stdio.h>
#include <string.h>
#define DIM(array) (sizeof(array)/sizeof(*array))
int lookup_keyworld(const char* key, const char* table[], const int arraysize)
{
int ret = -1;
int i = 0;
for (i = 0; i<arraysize; i++)
{
//注意第二个参数要使用*(table+i),这样才能获得当前第i个字符串的指针
if (strcmp(key, *(table + i)) == 0)
{
ret = i;
break;
}
}
return ret + 1;
}
int main()
{
const char* keyworld[] = {
"const",
"int",
"char",
"double",
"while",
"if-else",
"float",
"typedef",
"define"
};
int i = lookup_keyworld("int", keyworld, DIM(keyworld));
printf("%d\n", i);
return 0;
}