25. 指针数组和数组指针分析

思考

下面这些声明合法吗?

问题

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

在C语言中,matrix[3][3] 是一个二维数组,它包含3行和每行3个整数。对于二维数组,数组名 matrix 在大多数上下文中会被当作指向其首元素的指针,这里的首元素是一个包含3个整数的数组。因此,matrix 的类型实际上是 int (*)[3],即指向一个包含3个整数的数组的指针。
这里的关键点在于, matrix 并不直接指向二维数组中的第一个整数,而是指向整个第一行。当你对 matrix 进行解引用时(例如 *matrix),会得到第一行的数组,可以进一步访问这个数组的元素 ( 例如 (*matrix)[0] 是第一行的第一个元素 )。
#include <stdio.h>  
  
int main() {  
    int matrix[3][3] = {  
        {1, 2, 3},  
        {4, 5, 6},  
        {7, 8, 9}  
    };  
      
    // matrix 指向二维数组的第一行  
    int (*row_ptr)[3] = matrix; // row_ptr 是指向包含3个整数的数组的指针  
      
    // 访问第一行的第一个元素  
    printf("%d\n", (*row_ptr)[0]); // 输出 1  
      
    // 访问第二行的第一个元素  
    printf("%d\n", matrix[1][0]); // 输出 4,也可以写成 (*(matrix + 1))[0]  
      
    return 0;  
}

array和&array的地址值相同,但是意义不同,那么指向它们的指针类型相同吗?

1. array:这是一个数组名,在大多数上下文中,它会被当作指向数组首元素的指针。所以,array 的类型是 int*,它指向数组的第一个元素。
2. &array:这是一个指向整个数组的指针。它的类型是 int (*)[5],表示一个指向包含5个整数的数组的指针。
因此,虽然 array 和 &array 的地址值可能相同,但它们所指向的对象的类型是不同的,所以指向它们的指针类型也是不同的。

数组类型

C语言中的数组有自己特定的类型, 数组的类型由 元素类型数组大小 共同决定
例: int array[5]的类型为int[5]

定义数组类型

C语言中通过typedef为数组类型重命名
typedef type(name)[size];
数组类型:
typedef int(AINT5)[5];//定义一个AINT5型数组,里面的元素是int类型,数组大小是5
typedef float(AFLOAT10)[10];
数组定义:
AINT5 iArray;
AFLOAT10 fArray;

数组指针

数组指针 用于指向一个数组
数组名是数组首元素的起始地址,但并不是数组的起始地址
通过将取地址符&作用于数组名可以得到数组的起始地址
可通过数组类型定义数组指针:  
                 typedef type( ArrayType )[size];
                ArrayType* pointer;
也可以直接定义: type (*pointer)[n];
.  pointer为数组指针变量名
.  type为指向的数组的类型
.  n为指向的数组的大小

例子(数组指针定义、使用、运算)

#include <stdio.h>
typedef int(AINT5)[5];//定义一个AINT5型数组,里面的元素是int类型,数组大小是5
typedef float(AFLOAT10)[10];
typedef char(ACHAR9)[9];
int main()
{
    AINT5 a1;//相当于 int a1[5];
    float fArray[10];
   AFLOAT10* pf = &fArray;//pf是数组指针,存储fArray的数组地址,指向数组fArray
    ACHAR9 cArray;
   char(*pc)[9] = &cArray;//用偷懒的方式定义了一个数组指针pc,指向cArray
    char(*pcw)[4] = cArray;//数组指针pcw,指向数组cArray的首地址,把char[9]类型的地址赋值给含有4个字符数组的指针(char (*pcw)[4],不合理
   
    int i = 0;
   
    printf("%d, %d\n", sizeof(AINT5), sizeof(a1));
   
    for(i=0; i<10; i++)
    {
        (*pf)[i] = i;//(*pf):pf指向的数组fArray
    }
   
    for(i=0; i<10; i++)
    {
        printf("%f\n", fArray[i]);
    }
   
    printf("%0X, %0X, %0X\n", &cArray, pc+1, pcw+1);
    //pc+1, pcw+1增加了指向数组元素的指针的偏移量。
    //pc+1等价于(unsigned int)pc+1*sizeof(*pc)=(unsigned int)pc+sizeof(char[9])
    //pcw+1等价于(unsigned int)pc+1*sizeof(*pcw)=(unsigned int)pc+sizeof(char[4])
    //pc是数组指针变量,解引用后得到一个char类型的数组pc[9],sizeof(pc)=9
}
result:
warning:不合理那里
20, 20
0.000000
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000
7.000000
8.000000
9.000000
61FDA7, 61FDB0, 61FDAB

指针数组

指针数组是一个 普通的数组
指针数组中每个元素为一个指针
指针数组的定义: type* pArray[n];
type*为数组中每个元素的类型
pArray为数组名
n为数组大小

指针数组的使用---关键字查找

#include <stdio.h>
#include <string.h>
int lookup_keyword(const char* key, const char* table[], const int size)//const char* table[],指针数组
{
    int ret = -1;
   
    int i = 0;
   
    for(i=0; i<size; i++)
    {
        if( strcmp(key, table[i]) == 0 )//strcmp函数:如果两个字符串相同,则返回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"
    };
   
    printf("%d\n", lookup_keyword("return", keyword, DIM(keyword)));
    printf("%d\n", lookup_keyword("main", keyword, DIM(keyword)));
}
result:4   -1

main 函数的参数

main函数可以理解为操作系统调用的函数
在执行程序的时候可以向main 函数传递参数
int main()
int main(int argc)
int main(int argc, char  *argv[])
int main(int argc, char  *argv[], char *env[])
argc – 命令行参数个数
argv – 命令行参数数组
env – 环境变量数组

命令行参数的使用(如何使用main函数参数)

#include <stdio.h>
int main(int argc, char* argv[])
{
    int i = 0;
   
    printf("============== Begin argv ==============\n");
   
    for(i=0; i<argc; i++)
    {
        printf("%s\n", argv[i]);
    }
   
    printf("============== End argv ==============\n");
   
    printf("\n");
    printf("\n");
    printf("\n");
   
}

加入打印整个系统的环境变量

#include <stdio.h>
int main(int argc, char* argv[], char* env[])
{
    int i = 0;
   
    printf("============== Begin argv ==============\n");
   
    for(i=0; i<argc; i++)
    {
        printf("%s\n", argv[i]);
    }
   
    printf("============== End argv ==============\n");
   
    printf("\n");
    printf("\n");
    printf("\n");
   
    printf("============== Begin env ==============\n");
   
    for(i=0; env[i]!=NULL; i++)
    {
        printf("%s\n", env[i]);
    }
   
    printf("============== End env ==============\n");
}

小结

数组指针 本质上是一个 指针
数组指针指向的值是 数组的地址
指针数组 本质上是一个 数组
指针数组中 每个元素的类型是指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值