start from P158
8.2.4 指向数组的指针
int vector[10], *vp = vector; //正确,vector和vp具有相同类型:指向整型的指针。
int matrix[3][10], *mp = matrix; //错误,matrix不是指向整型的指针,而是指向整型数组的指针,mp是指向整型的指针。
指向整型数组的指针该这么定义:int (*p)[10]; //首先执行间接访问,故p是个指针,然后执行下标引用,故p指向的是某种类型的数组;
初始化:
int (*p)[10] = matrix; //使p指向matrix的第一行,逐行访问;
int *pi = &matrix[0][0]; //指向matrix的第一个元素,逐个访问;
int *pi = matrix[0]; //指向matrix的第一个元素,逐个访问;
8.2.5作为函数参数的多维数组
作为函数参数的多维数组名的传递方式和一维数组名相同——实际传递的是个指向数组第一个元素的指针。
区别:多维数组的每个元素本身是另外一个数组,编译器需要知道它的维数,以便为函数形参的下标表达式进行求值。
例:
int vector[10];
...
func1(vector);
参数vector的类型是指向整型的指针,所以func1的原型可以是以下其一:
void func1(int *vec);
void func1(int vec[ ]);
下面看一个矩阵:
int matrix[3][10];
...
func2( matrix );
这里参数matrix 的类型是指向包含10个整型元素的数组的指针。func2的原型应该是:
void func2( int (*p)[10] );
void func2( int p[ ][10]); //这个函数中,p的第一个下标根据包含10个元素的整型数组的长度进行调整,接着第二个下标根据整型的长度进行调整。必须知道第二个及以后各维的长度才能对下标进行求值,第一维的不需要知道。
8.2.6初始化
多维数组初始化:
int tow_dim[3][5] = { ★, ★, ★ };
★ 实际上是包含五个元素的整型数组,所以:
int tow_dim[3][5] = {
{ 00, 01, 02, 03, 04},
{ 10, 11, 12, 13, 14},
{ 20, 21, 22, 23, 24}
};
对于数组 int four_dim[2][2][3][5] 要使[0][0][0][0]初始化为100,[1][0][0][0]初始化为200,则:
int four_dim[2][2][3][5] = {
{
{
{100}
}
},
{
{
{200}
}
}
}
8.3指针数组
int *api[10];
下标引用的优先级高于间接访问,首先执行下标引用。因此,api是某种类型的数组,去的一个数组元素后再执行间接访问操作,这个表达式不再有其他操作,所以它是一个整型值。
例子:
char const *keyword[] = {
"do",
"for",
"if",
"register",
"return",
"switch",
"while"
};
#define N_KEYWORD (sizeof(keyword)/sizeof(keyword[0]))
printf("%d \n", sizeof(keyword)); //结果为28,由于是指针,所以4*7 = 28
printf("%c \n", *keyword[0]); //结果为d
printf("%d \n", sizeof(keyword[0])); //结果为4
8.4总结
数组名的值是指向数组第一个元素的指针。
例外:
sizeof返回整个数组所占用的字节而不是一个指针所占用的字节。
单目操作符&返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。
一个指针占据4个字节。
第9章
字符串长度:
size_t strlen( char const *string ); //szie_t 是无符号数;
不受限制的字符串函数
复制字符串:
char *strcpy( char *dst, char const *src ); //把参数src字符串复制到dst参数。
连接字符串:
char *strcat( char *dst, char const *src );
字符串比较:
int strcmp( char const *s1, char const *s2); // s1 < s2 返回小于0的值, s1 = s2 返回等于0的值,s1 > s2 返回大于0的值。
长度受限的字符串函数
char *strncpy( char *dst, char const *src, size_t len ); //超出部分不以NUL结尾
char *strncat( char *dst, char const *src, size_t len ); //总是在结果字符串后面添加一个NUL字节
int strncmp( char const *s1, char const *s2, size_t len ); //最多比较len个字节
第10章
结构声明:
struct tag { member-list } variable-list ;
例子:
struct {
int a;
char b;
float c;
} x ;
struct {
int a;
char b;
float c;
} y[20], *z ;
z = &x //这个不对,编译器认为是两个不同的结构!
但是:
struct SIMPLE{
int a;
char b;
float c;
};
struct SIMPLE x;
struct SIMPLE y[20], *z; //x, y, z都是同一种类型的结构变量。
声明结构的时候,可以使用的一种良好技巧:
用typedef创建一种新类型:
typedef struct {
int a;
char b;
float c;
} Simple; //现在Simple是个类型名,而不是结构标签。
结构成员的间接访问:
void func( struct COMPLEX *cp ) ;
可以用如下方式访问这个变量所指向的结构的成员f:
( *cp ).f;
箭头操作符接受两个操作数,但左操作数必须是一个指向结构的指针。
cp -> f;
cp -> a;
第13章
13.2 高级声明
int f( ); //它把f声明为一个函数,返回值是一个整数。
int *f( ); //先执行函数调用,故f是一个函数,在执行间接访问,返回值类型好似一个指向整型的指针。
int (*f)( );