数组、指针数组与数组指针

来源:互联网 发布:什么是淘宝客单价 编辑:程序博客网 时间:2024/06/04 20:07

一、数组类型

注意:
(1)数组首元素的地址与数组地址是完全两个不同的概念

int a[10];printf("a : %d,  a + 1 : %d\n", a, a + 1);printf("&a : %d,  &a + 1 : %d\n", &a, &a + 1);

输出结果:

这里写图片描述

(2)数组元素的首地址是常量,不能修改,这是为了释放内存空间所必需的,否则找不到释放内存空间的首地址了

(3)定义一个数组类型
定义数组类型的格式如下:

typedef int(ARRAY)[5];

其中ARRAY便是这个数组类型的名字。

举个例子:

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){    typedef int(ARRAY)[5];    ARRAY a;    //相当于 int a[5];    for (int i = 0; i < 5; i++)        a[i] = i + 1;    for (int i = 0; i < 5; i++)        printf("a[%d] : %d\n", i, a[i]);    system("pause");    return 0;}

输出结果:

这里写图片描述

二、指针数组

1、指针数组的定义

int *a[5];

a就是一个指针数组

2、指针数组的应用

(1)菜单

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>//获取菜单中标题的位置下标int getpos(char** mymenu, const char* key, int* pos) {    int ret = 0;    if (mymenu == NULL || key == NULL || pos == NULL) {        ret = 1;        printf("func getpos mymenu == NULL || key == NULL || pos == NULL err : %d\n", ret);        return ret;    }    *pos = 0;    for (int i = 0; mymenu[i] != NULL; i++) {        if (strcmp(key, mymenu[i]) == 0) {            *pos = i;            return ret;        }    }    return ret;}int main() {    int pos = 0;    char* mymenu[] = { "while", "for", "do", "switch", "case", 0 };    char key[64] = "do";    getpos(mymenu, key, &pos);    printf("pos : %d\n", pos);    for (int i = 0; mymenu[i] != NULL; i++) {        printf("%s\n", mymenu[i]);    }    system("pause");    return 0;}

输出结果:
这里写图片描述

mymenu是个指针数组,传给行参时,可以是char** mymenu,也可以是char* mymenu[],指针数组传参时会退化成指针,这是C语言的强大,不需要知道这个数组里面究竟放了几个元素,可以根据最后一个元素为空,这就需要用到指针数组的自我结束能力,或者传给一个数组大小的参数。

这里牵扯到指针数组的自我结束能力,也就是说程序员在定义指针数组的元素时,把最后一个设为空,那么编译器就能知道到这里就结束了。

比如:

char* mymenu1[] = { "while", "for", "do", "switch", "case", '\0' };char* mymenu2[] = { "while", "for", "do", "switch", "case", 0 };char* mymenu3[] = { "while", "for", "do", "switch", "case", NULL };

这里的三种结束方式都是可以的。

(2)命令行

int main(int argc, char* argv[], char** env) {    printf("\n-----------------begin argv-------------------\n");    for (int i = 1; i < argc; i++) {        printf("%s\n", argv[i]);    }    printf("\n-----------------end argv-------------------\n");    printf("\n-----------------begin env-------------------\n");    for (int i = 0; env[i] != NULL; i++) {        printf("%s\n", env[i]);    }    printf("\n-----------------end env-------------------\n");    system("pause");    return 0;}

输出结果(这里是用cmd执行的):
这里写图片描述

可以看到main函数的参数argv和env实际都是二级指针,argv写成了指针数组的形式而已。

再扩展一下main函数的内存分配,都知道main函数是程序的入口,那么exe程序跑起来,也就是操作系统调用了main函数,那么就有操作系统为main函数分配内存空间,调起来之后再把内存空间的首地址扔给main函数,让main函数继续执行内存的分配释放等各种操作。比如上面菜单的那个例子main函数调用了getpos函数,则由main函数为getpos分配内存空间,也就是说谁调用的谁就去分配内存空间。

所以说在企业的项目开发过程中,不管是使用的MFC框架,QT框架,还是linux内核,程序员只是使用各种api,往里面填参数而已,实际都是框架里把内存分配好了。

三、数组指针

1、数组指针的定义方式

(1)数组类型定义

typedef int(arrayType) [5];int a[3][5];arrayType* myarray = &a;

(2)数组指针类型

typedef int(*pArrayType) [5];int a[3][5];pArrayType pArray = &a;

(3)直接定义

int a[3][5];int (*pArray)[5] = a;

2、多维数组的本质

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>int print_array(int* array, int n, int m) {    int ret = 0;    if (array == NULL) {        ret = 1;        printf("func print_array err : %d\n", ret);        return ret;    }    for (int i = 0; i < n * m; i++) {        printf("%d ", array[i]);    }    printf("\n");    return ret;}int main(){    int a[3][5];    printf("a : %d,  a + 1 : %d\n", a, a + 1);    printf("&a : %d,  &a + 1 : %d\n", &a, &a + 1);    int(*pArray)[5] = a;    int temp = 1;    printf("pArray : %d, pArray + 1 : %d\n", pArray, pArray + 1);    for (int i = 0; i < 3; i++) {        for (int j = 0; j < 5; j++) {            *(*(pArray + i) + j) = temp++;        }    }    print_array((int*)a, 3, 5);    system("pause");    return 0;}

输出结果:

这里写图片描述

可以看到a是二维数组的首元素地址,a + 1跳了一个一位数组的距离,也就是5 * 4 = 20个单位,跟数组指针加1跳的步长是一样的。&a是整个二维数组的首地址,&a + 1跳了5 * 4 * 3 = 60个单位。

二维数组赋给数组指针后,可以通过数组指针改变二维数组的值,先看以前写的一位数组转指针的过程:

a[i] ===》  a[0 + i] ===》  *(a + i)

那么二维数组转数组指针是一个道理

a[i][j] ===》 a[0 + i][j] ===》 *(a + i)[j]  ===》  *(a + i)[0 + j]  ===》  *(*(a + i) + j)

3、多维数组在内存中的存储

虽然是多维数组,但实际多维数组在内存中还是按照线性存储的,从上面的代码中看出,在print_array函数中的第一个形参是一级指针,利用这个一级指针仍然把二维数组的值给打印出来了。

0 0
原创粉丝点击