[day04]数组类型基础、数组指针、多维数组的本质、指针数组

1.数组类型基础

1.int a[10] = {1,2};

a代表数组首元素的地址,不是整个数组的地址,数组首元素的类型。

&a 代表整个数组的地址,数组类型 int[10]。

&a与a代表的数据类型不一样。

这条结论可以通过第3点的两个printf得以验证,一个+20,一个加+4。

2.

1 int c[20] = {0}; 

1 memset(c, 0, sizeof(c));

区别

前者编译期间搞定,后者相当于手工使用一个循环搞定。

3.数组类型

1 typedef int(MyArr5)[5]; //声明一个数组类型
2 MyArr5 arr5; //相当于int arr5[5];
3 
4 /* 指针步长问题*/
5 printf(“%d %d\n”, &arr5, &arr5 + 1); // +20
6 printf(“%d %d\n”, arr5, arr5 + 1); // +4

 

2.数组指针

1.数组首元素地址

1 int a[5] = {1, 3, 4, 55, 6};
2 // a为数组首元素地址,是个常量指针,不能被修改;
3 a = 0x11; // 错误

2.间接数组指针定义

1 typedef int(MyArr5)[5]; //声明一个数组类型
2 MyArr5 *pArray = &a; //注意要&a,虽然不加&貌似也能得出正确结果
3 /* 相当于是数组中存了5个指针,循环打印时,使用*取值,再加下标访问即可。 如: */
4 printf(“%d ”, (*pArray)[i]);

3.直接数组指针定义

1 typedef int(*PMyArr5)[5]; //声明一个数组指针类型
2 PMyArr5 myp = NULL;
3 myp = &a;
4 
5 printf(“%d ”, (*myp)[i]);
6 
7 /* 直接一步了当 */
8 int (*myparra)[5] = &a;

 

3.多维数组的本质

1.对int myarray[3][5]; 中myarray的理解

myarray是数组首元素的地址

myarray是一个常量指针

myarray是一个数组指针

2.测试步长

 1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5          //1 myarray数组首元素的地址吧
 6          //2 myarray是一个常量指针 
 7          //3 myarray是一个数组指针
 8          int myarray[3][5];
 9 
10     printf("myarray:%d myarray+1:%d\n", myarray, myarray+1); //+20
11     printf("&myarray:%d &myarray+1:%d\n", &myarray, &myarray+1); //+60
12 
13     return 0;
14 }

3.数组指针操作

1 int (*p)[5] = myarray; // 直接赋值操作就行了
2 printf(“%d ”, p[i][j]); // 直接打印即可

4.一点总结

1 不管是几维数组,都是线性存储的。所以会存在多维数组做函数参数,退化问题。

2 多维数组做函数参数 二维数组,能勉强表达出来。但是三维数组,四维数组,就表达不出来了。

结论:指针做函数参数,有效内存维数,只到2级。如果你看到3级指针 4级指针,它表示的不是内存的维数。

1 *(*(myarray+i)+j ) 

直接就相当于

1 myarray[i][j]

5.二维数组强转成一维指针,打印。(线性存储)

 1 #include <stdio.h>
 2 
 3 void printArr(int *a, int iNum)
 4 {
 5     int i;
 6     for (i=0; i<iNum; i++) {
 7         printf("%d ", a[i]);
 8     }
 9 }
10 
11 int main(void)
12 {
13     int myarray[3][5];
14 
15     int i, j;
16     int tmp = 0;
17 
18     for (i=0; i<3; i++) {
19         for (j=0; j<5; j++) {
20             *(*(myarray+i)+j) = tmp ++;
21         }
22     }
23 
24     printArr((int *)myarray, 3*5);
25 
26     return 0;
27 }
 6.二级指针第二种内存模型做函数参数(使用数组指针)

原本第二种模型为
main:

char arr[3][5] = {“abc”, “aaa”, “acd”};

Func:

Func(char arr[3][5], int iNum);

根据一级指针传参推演过程:

Func(char arr[5], int iNum)->Func(char arr[], int iNum)->Func(char *arr, int iNum);

得到二级指针传参推演过程:

Func(char arr[3][5], int iNum)->Func(char arr[][5], int iNum)->Func(char (*arr)[5], int iNum);

 

 

4.指针数组

指针数组例子

 1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5     //指针数组
 6     char *p1[] = {"123", "456", "789"};
 7     int i;
 8 
 9     printf("p1:%d p1+1:%d\n", p1, p1+1); // 4
10     printf("&p:%d &p1+1:%d\n", &p1, &p1+1); //12
11 
12     for (i=0; i<3; i++)
13         printf("%s ", p1[i]);
14 
15     return 0;
16 }

可以当做二维数组理解?(不是说可以当作二维数组理解,无论是一维数组还是二维数组,&p1都是整个数组的地址,因为它是指针数组,它原生就是数组,只是存放指针而已)。

一样的p1代表首元素的地址,&p1代表整个数组的首地址?

注意:在主函数中使用sizeof(p1)/sizeof(*p1)计算size是没有问题了,但是如果在被调用函数中使用这样的方法求是有问题的,因为数组做函数参数会退化,求出来就是1了。

指针数组应用场景

#include <stdio.h>
#include <stdlib.h>

// 场景1,main函数的参数
int main(int argc, char **argv, char **env)
{
    // 可以直接打印argv以及env,不需要用到argc
    int i = 0;

    for (; argv[i] != NULL; i++){
        printf("%s\n", argv[i]);
    }

    for (i=0; env[i] != NULL; i++){
        printf("%s\n", env[i]);
    }

    //场景2,做菜单
    char *pmenu[] = {
        "aa",
        "bb",
        "cc",
        0
    };

    for (i = 0; pmenu[i] != NULL; i++) {
        printf("%s\n", pmenu[i]);
    }

    system("pause");

    return 0;
}
posted @ 2014-12-30 22:12  IFPELSET  阅读(167)  评论(0编辑  收藏  举报