C语言-第25课 - 指针数组和数组指针分析

时间:2022-05-07 16:45:53

第25课 - 指针数组和数组指针分析

 

思考:

下面这些声明合法吗?
int array[5];     常规数组

int matrix[3][3];   二维数组

int* pA = array;   pA指针用array初始化,pA指向的是首元素的地址,pA不是数组指针

int* pM = matrix;  pM指针用matrix初始化

问题:

 

l array代表数组首 元素地址,那么matrix代表什么?

l arrry(数组首元素的地址,int*类型)和&array(数组的起始地址)的地址相同,但是意义不同,那么指向它们的指针类型相同吗?

一般情况下声明一个数组之后,比如int array[5],数组名array就是数组首元素的首地址,而且是一个地址常量。但是,在函数声明的形参列表中除外。

C中, 在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址。 它的类型取决于数组元素的类型: 如果它们是int类型,那么数组名的类型就是指向int的常量指针——C和指针》

在以下两中场合下,数组名并不是用指针常量来表示,就是当数组名作为sizeof操作符和单目操作符&的操作数时。 sizeof返回整个数组的长度,而不是指向数组的指针的长度。 取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量的指针。所以&a后返回的指针便是指向数组的指针,跟a(一个指向a[0]的指针)在指针的类型上是有区别的。——C和指针》

“+1”就是偏移量问题:一个类型为T的指针的移动,是以sizeof(T)为移动单位。 
array+1:在数组首元素的首地址的基础上,偏移一个sizeof(array[0])单位。此处的类型T就是数组中的一个int型的首元素。由于程序是以16进制表示地址结果,array+1的结果为:0012FF34+1*sizeof(array[0])=0012FF34+1*sizeof(int)=0012FF38 
&array+1:在数组的首地址的基础上,偏移一个sizeof(array)单位。此处的类型T就是数组中的一个含有5int型元素的数组。由于程序是以16进制表示地址结果,&array+1的结果为:0012FF34+1*sizeof(array)=0012FF34+1*sizeof(int)*5=0012FF48。注意1*sizeof(int)*5(等于00000014)要转换成16进制后才能进行相加。

 

 

  1. 数组类型

1c语言中的数组有自己特有的类型,数组的类型由元素类型和数组大小共同决定。

eg

int array[5]的类型为int[5];

2C语言中通过typedef为数组类型重命名:typedef type(name)[size]

eg

typedef int(AINT5)[5];

typedef float(AFLOAT10)[10];

数组定义:AINT5 iArray;

AFLOAT10 fArray;

 

 

 

 

  1. 数组指针

1)数组指针用于指向一个数组。

2)数组名是数组首元素的地址,但不是数组的起始地址。

3)通过取地址符&作用于数组名可以得到数组的起始地址。

int i[5]; int* PI = &i;

4)可通过数组类型定义数组指针:

ArrayType* pointer;(如AINT5* vp

也可以直接定义:type *pointer[n];

pointer为数组指针变量名,type为指向的数组的类型,n为指向的数组的大小。

int (*p)[n];

例程:

#include <stdio.h>

typedef int(AINT5)[5];

typedef float(AFLOAT10)[10];

typedef char(ACHAR9)[9];

// three array's type

int main()

{

    AINT5 a1;

    float fArray[10];

    AFLOAT10* pf = &fArray;

    ACHAR9 cArray;

    char(*pc)[9] = &cArray;  //数组指针

    char(*pcw)[4] = cArray;  //char*类型的指针赋值给数组指针,是不合理的,

    int i = 0;

    printf("%d, %d\n", sizeof(AINT5), sizeof(a1));

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

    {

        (*pf)[i] = i;

    }

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

    {

        printf("%f\n", fArray[i]);

    }

printf("%0X, %0X, %0X\n", &cArray, pc+1, pcw+1);

//pc+1   ----- (unsigned int)pc + 1*sizeof(*pc)

}

运行结果:

2020

0.000000

1.000000

2.000000

3.000000

4.000000

5.000000

6.000000

7.000000

8.000000

9.000000

18FEFC18FF0518FF00

分析:18FF0518FEFC差九个字节,18FF0018FEFC差四个字节。

 

 

  1. 指针数组

1)指针数组是一个普通的数组。

2)指针数组中每个元素为一个指针。

3)指针数组的定义:type* pArray [n];

type*为数组中每个元素的类型,pArray为数组名,n为数组大小。

eg:

 

例子:指针数组的使用,关键字查找

#include <stdio.h>

#include <string.h>

int lookup_keyword(const char* key, const char* table[], const int size)

{

    //数组在函数中变成了一个指针,大小必须要另一个变量来定义

int ret = -1;

    int i = 0;

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

    {

        if( strcmp(key, table[i]) == 0 )

        {

            ret = i;

            break;

        }

    }  

    return ret;

}

#define DIM(a) (sizeof(a)/sizeof(*a))

int main()

{

    const char* keyword[] = {

            "do",

            "for",

            "if",

            "register",

            "return",

            "switch",

            "while",

            "case",

            "static"

    };//char*指向字符串

    printf("%d\n", lookup_keyword("return", keyword, DIM(keyword)));

    printf("%d\n", lookup_keyword("main", keyword, DIM(keyword)));

}

运行结果:

4

-1

 

 

 

  1. main函数的参数

1main函数可以理解为操作系统调用的函数。

2)在执行程序的时候可以向main函数传递参数。

int main()

int main(int argc)

int main(int argc, char* argv[])

int main(int argc, char* argv[], char* env[])

argc:命令行参数个数

argv:命令行参数数组

env:环境变量数组

例子:

#include <stdio.h>

#include <string.h>

int lookup_keyword(const char* key, const char* table[], const int size)

{

    //数组在函数中变成了一个指针,大小必须要另一个变量来定义

int ret = -1;   

    int i = 0;  

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

    {

        if( strcmp(key, table[i]) == 0 )

        {

            ret = i;

            break;

        }

    }    

    return ret;

}

#define DIM(a) (sizeof(a)/sizeof(*a))

int main()

{

    const char* keyword[] = {

            "do",

            "for",

            "if",

            "register",

            "return",

            "switch",

            "while",

            "case",

            "static"

    };//char*指向字符串  

    printf("%d\n", lookup_keyword("return", keyword, DIM(keyword)));

    printf("%d\n", lookup_keyword("main", keyword, DIM(keyword)));

}

运行结果:(打印命令行和windows下面的一些信息)

 

小结:

l 数组指针本质是一个指针

l 数组指针指向的值是数组的地址

l 指针数组本质上是一个数组

l 指针数组中每个元素的类型都是指针