数组与指针

1. 数组与指针

1.1  一维数组与指针

例子:

int a[] = { 1,2,3,4,5,6,7,8,9 ,0 };
for (int *p = a; p < a + 10; p++)
{
   std::cout << p << ',' << *p << std::endl;
}

指针格式:int a[10] 退化为指针是指向一个元素的指针,故int *p = a;

访问数组的方式:p[i], *(p + i);

1.1  二维数组与指针

例子1:

char *s[] = { "cacul","paint","notepad" };
for (char**p = s; p < s + 3; p++)
{
    std::cout << *p << std::endl;
}

上述内存模型可解释如下:

数组s

常量区

地址A

地址A

cacul

地址B

地址B

paint

地址C

地址C

notepad

数组s中实际存的是每个字符串的地址,所以可以使用二级指针去访问。实际解释如下:

  1. s中每个元素是一个地址,为char *类型,该地址指向一个字符数组。
  2. char* s[]实际也是一个指针数组,故只需再加一级指针就可以访问对应元素了。

例子2:

char *s2[3][10] = { "cacul","paint","notepad" };
for (char**p = s2; p < s2 + 3; p++)
{
    std::cout << *p << std::endl;
}

这个例子将无法编译通过,报错如下:

a value of type "char *(*)[10]" cannot be used to initialize an entity of type "char **"

说明二级指针和二维数组的指针的类型不同。

结论: 地址相同不等价于类型相同,这里需要一个数组类型的指针

例子3:

    char s2[3][10] = { "cacul","paint","notepad" };
    printf("%p,%d,%d
%p,%d,%d
%p,%d
", s2,  sizeof(s2),  sizeof(*(&s2)),
                                          &s2, sizeof(&s2), sizeof(*(*s2)),
                                          *s2, sizeof(*s2));

运行结果:

004AFB84,30,30

004AFB84,4,1

004AFB84,10

结论:地址一样,但类型不一样,&s2整个数组的首地址,s2第一行的首地址,*s2第一个字符的地址。

二维数组的遍历

例子3:

    int b[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    //二维数组的遍历,因为在内存中是线性存储的
    for (int *p = &b[0][0]; p < &b[0][0] + 12; p++)
    {
        std::cout << *p << std::endl;
    }

扩展:

指针的运算

int *p = &b[0][0];

*(p+4); //等于5,实际移动的长度是4*sinzof(type)

数组作为会退化为指针,即实际穿首地址。

例子:

int getSize(int a[3][4])
{
    printf("%d", sizeof(a));

}
int main()

{
    int b[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    getSize(b);
    system("pause");
    return 0;
}

运行结果:4

  1. 一维数组a[n]做参数会退化成指向第一个元素的指针
  2. 二维数组a[m][n]做参数也会退化成指向第一个元素的指针,而第一个元素是一个长度为n的数组,故是一个数组指针 (*p)[n];

例子:

int getMax(int (*a)[4])
{
    int tmp = *(*(a + 0) + 0);
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (a[i][j] > tmp)
            {
                tmp = a[i][j];
                //tmp = *(*(a + i) + j);
            }
        }
    }
    return tmp;
}

调用:

std::cout << getMax(b) << std::endl;

工具:

API介绍:

HWND *win = FindWindowA("ClassName", "WindowName");//寻找桌面窗口

SetWindowPos(win,坐标,大小)用于设置窗口坐标和大小。

1.2 三维数组

例子:

    int c[3][4][5] = { 0 };
    for (int *p = &c[0][0][0], i = 0; p < &c[0][0][0] + 60; p++, i++)
    {
        *p = i;
    }
    int(*d)[4][5] = c;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            for (int k = 0; k < 5; k++)
            {
                //std::cout << c[i][j][k] << "	";//这三种都可以
                //std::cout << d[i][j][k] << "	";
                std::cout << *(*(*(d+i)+j)+k) << "	";
            }
            std::cout << std::endl;
        }
        std::cout << std::endl << std::endl;
    }

由二维数组一样可以扩展到三维数组,所需指针即为指向一个二维数组的数组指针。

1.3 总结

N级指针不可用于数组。(会报类型不同的错误)

定义               指针                  访问

int a[10];       int *p = a;           p[i]; *p;

int b[3][4];     int (*b)[4] = b;     b[i][j]; *(*(b + i) + j);

int c[3][4][5];  int(*d)[4][5] = c;   d[i][j][k]; *(*(*(d+i)+j)+k);

GCC和VCC编译器的区别:

GCC编译:

int num = 100;

int a[num];

上述代码可以编译通过。

VCC编译:

int num = 100;

int a[num];

不能编译通过,必须为常量,即int a[100]。

这种定义的变量都在栈里面,当定义int a[1024*1024]时会发生栈溢出。

原文地址:https://www.cnblogs.com/UFO-blogs/p/9708374.html