C语言技巧--结构体指针的强制转换

关于强制类型转换

总所周知,在编程语言中的强制类型转换可以将已经既定的数据类型强制转换成所需要的目的类型。其实强制类型转换的过程中并不会改变数据内存中存贮的具体二进制的值,而是仅使编译器对此内存块内的数据的解释方法做出一个改变,因此这种操作并不占用程序运行的时间而仅仅对工程的编译时间有所影响,同时适当的强制类型转换更能灵活地操作数据并提高代码的可读性。

而对于指针的强制类型转换,由于其并不会改变指针对象所存储的值(即所指向的地址不变),经过强制类型转换之后仅仅只改变指针所指向地址的数据的解释方法(如数据类型、数据大小等),如下:

char a = 'a';
char * b = &a;
char * c = b;
(int *) c;
int * d = (int *) b;
printf("(int) char = %d \n", a);
printf("*(int *)(char *) c = %d \n", *c);
printf("*(int *)(char *) d = %d \n", *d);
printf("*(char *) c = %c \n", *(char *)c);

输出结果为:

(int) char = 97 
*(int *)(char *) c = 97 
*(int *)(char *) d = -956104607 
*(char *) c = a 

可以发现当小类型指针向大类型指针进行强制类型转换是非常危险的(如:char->int),会带入未定义内存空间中的野值,先赋值再转换和先转换再赋值所得到的处理结果是不一样的;而大类型指针向小类型指针进行强制类型转换则不存在这种危险。

结构体的应用

由上述可以知道,对于结构体的指针进行类型转换也只改变指向位置的内容的解释方法,因此类似于这种方法便可以快捷访问到结构体中的特定位置的数据(注意字节对齐):

typedef struct A{
    int a1;
    int a2;
    int a3;
}A;

int main(){
    A b;
    b.a1=1;b.a2=2;b.a3=3;
    int * a = &b;
    printf("a1 = %d \n",*a);
    printf("a2 = %d \n",*(a+1));
    printf("a3 = %d \n",*(a+2));
    
    return 0;
}

输出结果为:

a1 = 1 
a2 = 2 
a3 = 3 

由于a为int型的指针,因此a+1仅移动4个字节的位置,而不会移动到内存中结构体所占空间的外面,由此便可以快捷访问到结构体b中其他的元素了。

对这种方法进行引申,在结构体中加入链表结点、函数指针等数据,便可以通过链表节点的操作轻松方便地将各种不同的节点进行连接和处理了(通过(StructA *) pNode),再通过判断结构体的类型根据导入的函数指针等接口,利用回调函数等方法便可以轻松的实现扩展链表节点、管理结构体组等,如下:

typedef struct Node{
    Node * pNext, * pPre;
};

typedef struct Stack{
    Node * pNodeTop;
    //Data&Control
};

typedef struct StructA{
    Node * pNode;
    //Func&Data
};

//通过Stack_pop()、Stack_push(Node)等控制Stack Node
//通过(StructA *) pNode访问Node扩展数据

你可能感兴趣的:(c语言,链表)