| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4740 人关注过本帖, 1 人收藏
标题:大神进~关于结构体数据的强制类型转换~已经晕头转向~
只看楼主 加入收藏
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
结帖率:90.24%
收藏(1)
已结贴  问题点数:20 回复次数:8 
大神进~关于结构体数据的强制类型转换~已经晕头转向~
#include <stdio.h>
#include <malloc.h>
#include "LinkList.h"

typedef void LinkList;
typedef struct _tag_LinkListNode LinkListNode;


typedef struct _tag_LinkList
{
    LinkListNode header;                //线性表首地址也即表头
    int length;                         //线性表长度也即表长
} TLinkList;

LinkList* LinkList_Create() // O(1)
{
    TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList));
   
    if( ret != NULL )
    {
        ret->length = 0;                //当前数组长度置0
        ret->header.next = NULL;        //头指针的next为空
    }
   
    return ret;
}

void LinkList_Destroy(LinkList* list) // O(1)
{
    free(list);
}

void LinkList_Clear(LinkList* list) // O(1)
{
    TLinkList* sList = (TLinkList*)list;
   
    if( sList != NULL )
    {
        sList->length = 0;                          
        sList->header.next = NULL;
    }
}

int LinkList_Length(LinkList* list) // O(1)
{
    TLinkList* sList = (TLinkList*)list;
    int ret = -1;                       
   
    if( sList != NULL )
    {
        ret = sList->length;
    }
   
    return ret;
}

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) // O(n)
{
    TLinkList* sList = (TLinkList*)list;
    int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
    int i = 0;
   
    if( ret )
    {
        LinkListNode* current = (LinkListNode*)sList;                  //  问题一 :此处强制类型转换将TLinkList*强制转换为LinkListNode*
        
        for(i=0; (i<pos) && (current->next != NULL); i++)
        {
            current = current->next;
        }
        
        node->next = current->next;
        current->next = node;
        
        sList->length++;
    }
   
    return ret;
}

LinkListNode* LinkList_Get(LinkList* list, int pos) // O(n)
{
    TLinkList* sList = (TLinkList*)list;
    LinkListNode* ret = NULL;
    int i = 0;
   
    if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
    {
        LinkListNode* current = (LinkListNode*)sList;
        
        for(i=0; i<pos; i++)
        {
            current = current->next;
        }
        
        ret = current->next;
    }
   
    return ret;
}

LinkListNode* LinkList_Delete(LinkList* list, int pos) // O(n)
{
    TLinkList* sList = (TLinkList*)list;
    LinkListNode* ret = NULL;
    int i = 0;
   
    if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
    {
        LinkListNode* current = (LinkListNode*)sList;
        
        for(i=0; i<pos; i++)
        {
            current = current->next;
        }
        
        ret = current->next;
        current->next = ret->next;
        
        sList->length--;
    }
   
    return ret;
}

struct Value
{
    LinkListNode header;
    int v;
};

 //  ———————————————————以此往下为主函数部分——————————————————————

int main(int argc, char *argv[])           
{
    int i = 0;
    LinkList* list = LinkList_Create();
   
    struct Value v1;
    struct Value v2;
    struct Value v3;
    struct Value v4;
    struct Value v5;
   
    v1.v = 1;
    v2.v = 2;
    v3.v = 3;
    v4.v = 4;
    v5.v = 5;
   
    LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list));     //问题二:强制类型转换,将&v1又转换为LinkListNode*类型
    LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list));
    LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list));
    LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list));
    LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list));
   
    for(i=0; i<LinkList_Length(list); i++)
    {
        struct Value* pv = (struct Value*)LinkList_Get(list, i);
        
        printf("%d\n", pv->v);
    }
   
    while( LinkList_Length(list) > 0 )
    {
        struct Value* pv = (struct Value*)LinkList_Delete(list, 0);
        
        printf("%d\n", pv->v);
    }
   
    LinkList_Destroy(list);
   
    return 0;
}


//这是基本的动态链表操作,只不过表中用了很多的强制类型转换。。。楼主不明白的是为什么所定义的结构体根本不同,却可以通过强制转换实现这些操作?
//还有就是什么时候可以强制转换什么时候不可以~
搜索更多相关主题的帖子: include 结构体 线性表 
2015-04-15 21:58
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 

既然还有不甘心
就还没到放弃的时候~
2015-04-15 21:58
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
给讲讲这些关于指针强制转换的原理吧!

既然还有不甘心
就还没到放弃的时候~
2015-04-15 22:02
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
收藏
得分:20 
又晕菜了?

问题一:强制类型转换将TLinkList*强制转换为LinkListNode*
类型 TLinkList 和 LinkListNode 是一个类型的二个别名

我们看 TListList 的声明:
typedef struct _tag_LinkList
{
    ...
} TLinkList;

就相当于:typedef struct _tag_LinkListNode TLinkList;

是不是和 typedef struct _tag_LinkListNode LinkListNode 完全等价?

问题二:强制类型转换,将&v1又转换为LinkListNode*类型

先看 struct Value 的声明:
struct Value
{
    LinkListNode header;
    int v;
};
比较一下 LinkListNode 的声明:
struct _tag_LinkList
{
    LinkListNode header;
    int length;
}
两者除了成员名字不同外,占用的内存大小和各自名字在里面的位置完全相同。

这就是一直以来 C 指针被人诟病的原因。 C 的指针访问,它就是个指向内存的指针,具体内存里是些什么,C 程序员可以十分自由地强行让指针按照自己设定的结构模型去访问。但通常来说,有经验的程序员会尽量保证强迫指针去访问与指针原始声明不太一样的数据结构的时候,尽量保持不越界。所以,完全可以随便分配一块4字节的内存块,一会儿告诉访问指针,这个四字节,里面放的是个整数,指针就会按照整数规则去存取,也可以改换一下,说这个四字节是二个中文字,每二个字节一个汉字,指针就会乖乖地按照WORD规则去访问。这种操作在字符编码转换中非常常见,特别是操作系统更底层的驱动程序等编写中,结构体强制类型转换更是比比皆是。

好,到这里你应该已经清楚,指针为什么可以这么访问了,但为什么代码还必须加个强制类型转换呢。这个本质上不是必须的,只是你不做类型转换,编译器就无法知道访问的尺度,编译器总是需要知道正在操作的内存,是个什么类型的内存,以便当你使用 ++ 或者 -- 的时候,它可以正确地移动访问指针。

幸好,你选择的例子里的几个看起来有点不太的声明,本质上是一个东西,其实,完全异类的结构都是可以强制相互转换的,只不过这时候你需要特别留意:编译器已经被你彻底搞瞎了,是否越界已经不能依靠编译器来告诉你了。
2015-04-16 00:52
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
收藏
得分:0 
C 是一个没啥太多规则的世界,你就是需要去平衡这样一个世界的上帝。所以,同样功能的 C 程序由不同的人来写,仔细体会,你可能看到的是一部惊险小说,也可能看到的是一部武打小说,但你一定会欣赏简约委婉的爱情小说,也一定会为超越福尔摩斯推理极致的侦探小说而倾倒。哈哈哈哈,等你能欣赏它,就再也不会头晕了。
2015-04-16 01:05
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
回复 5楼 AleTiff
your explain is so clear and detail , thank you so much!

既然还有不甘心
就还没到放弃的时候~
2015-04-16 14:29
z_j_j_1
Rank: 4
等 级:业余侠客
威 望:1
帖 子:62
专家分:213
注 册:2015-4-4
收藏
得分:0 
回复 5楼 AleTiff
需要好好拜读下了
2015-04-16 15:28
hackrol
Rank: 4
来 自:世界和平组织
等 级:业余侠客
帖 子:62
专家分:267
注 册:2014-9-6
收藏
得分:0 
指针 转换其实很简单,,,,,一个指针 有两个属性,,一个是内存地址,,另一个是从这个地址开始到哪里结束,就是指针指向的数据长度..
所以指针强制转换其实就是改变这个指针指向数据的长度属性....比如cha *转换成int*  内存地址还是一样的,只是长度从1 变成了4....
结构体与C++里的类指针都是同一个道理
2015-04-18 13:19
箫耒
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2018-4-13
收藏
得分:0 
回复 6楼 S140131022

2018-05-13 18:42
快速回复:大神进~关于结构体数据的强制类型转换~已经晕头转向~
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.038699 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved