单指针表示的隐式结构体数组以及其成员访问方式

当我们看到一个结构体指针的时候,不要下意识的觉得它只是指向某一个结构体实例的地址,因为该地址的内存单元的值是不确定的,如果在该内存起始位置分配了多个单位结构体大小的内存空间,那么该指针指向的地址也可以看做一个结构体数组。如下代码所示:

/*!
 * Description: 单指针表示的隐式结构体数组及其成员访问方式
 * Date: 2019-9-17
 * Author: HooY
 */

#include 
#include 

int main()
{

    struct A
    {
        char c;

        int seq;

    }*Atest,*tmp;

    Atest = (struct A*)malloc(sizeof(A) * 2);
    // Atest[0] = { 'a',1 };
    // Atest[1] = { 'a',2 };
    *Atest = { 'a',1 };
    *(Atest + 1) = { 'b',2 };


    tmp = Atest;
    printf(">>> '.'Access Style 1:\n");
    printf("  Atest[0]:%d\n", Atest[0].seq);
    printf("  Atest[1]:%d\n", Atest[1].seq);

    Atest = tmp;
    printf(">>> '.'Access Style 2:\n");
    printf("  Atest[0]:%d\n", (*Atest++).seq);
    printf("  Atest[1]:%d\n", (*Atest).seq);

    Atest = tmp;
    printf(">>> '->'Access Style 1:\n");
    printf("  Atest[0]:%d\n", Atest++->seq);
    printf("  Atest[1]:%d\n", Atest->seq);

    Atest = tmp;
    printf(">>> '->'Access Style 2:\n");
    printf("  Atest[0]:%d\n", Atest->seq);
    printf("  Atest[1]:%d\n", ++Atest->seq);

    return 0;
}

我们声明了一个A类型的结构体指针Atest,并在以Atest指向的地址作为起始地址,分配了2个A类型大小的内存空间。可以通过数组下标的方式Atest[0] = { 'a',1 },或者*号方式*Atest = { 'a',1 }对其分别赋值。然后通过'.'或者'->'方式访问结构体数组中单个结构体成员变量。

注意:因为Atest为stuct A类型的指针,所以在对该指针进行算术运算时,会以stuct A的大小做为单位偏移量计算地址,Atest+1的计算结果实际上是指向下一个stuct A的起始地址,同理使用数组下标表示的Atest[1],其中的[1]也是按stuct A的大小为单位偏移量计算地址。所以,以下表示方法是等效的。

Atest = &Atest[0], Atest+1 = &Atest[1]

用该方法表示结构体数组,有比较大的风险,比如,使用Atest[3]或者将Atest指针加2或者更大,会让Atest指向一片我们不清楚的内存区域,如果我们此时再对把Atest指向的内存空间按照stuct A类型读取或者修改,就会读到无意义的结果,或者改变其它变量存储的值,这是有风险的。使用的时候需要谨慎。

你可能感兴趣的:(C语言,C,结构体,指针)