| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2719 人关注过本帖
标题:结构体强制类型转换?
只看楼主 加入收藏
miku
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2014-6-7
收藏
得分:0 
谢谢4楼和6楼的提醒,也谢谢斑竹以及其他人的帮助,我对printf理解错了
char *string
*string="I love china"
如果要输出字符串用printf(%s\n,string)而不是printf(%s\n,*string),不过我很好奇printf(%s\n,*string)会输出什么,没法用电脑跑- -

2014-06-09 00:02
miku
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2014-6-7
收藏
得分:0 
没想到第一次发帖就是高亮,我的无知被版主点亮了 受宠若惊啊
2014-06-09 00:07
xsw07122269
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:34
专家分:183
注 册:2014-6-2
收藏
得分:0 
回复 4 楼 蚕头燕尾
其实我觉得你这样说是错误的。他这样赋值输出的一定是stu[0].name的值,不管这个结构体的第一个成员是不是name。他是把name数组的首地址送给P了,无非就是强制转换成了结构体类型而已,而p++的话指向的就是下一个结构体元素里面的name成员。我觉得这样的转换有时还是有意义的。
2014-06-09 05:24
xsw07122269
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:34
专家分:183
注 册:2014-6-2
收藏
得分:0 
回复 21 楼 miku
你这样输出的应该只是第一个字符。
2014-06-09 05:26
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:0 
回复 12 楼 TonyDeng
版主,说实话,我还真不知道为什么会有那样的输出.  

测试一下,输出了"AB",不过不明白为什么.尽管知道两个字符对应的ASCII码,仍旧没想明白.

为什么text.x就成了字符串了?

对于楼主在21楼提到的
程序代码:
谢谢4楼和6楼的提醒,也谢谢斑竹以及其他人的帮助,我对printf理解错了
char *string
*string="I love china"
如果要输出字符串用printf(%s\n,string)而不是printf(%s\n,*string),
不过我很好奇printf(%s\n,*string)会输出什么,没法用电脑跑- -


本人亲测在不同的编译器下会有不同的结果,  添加适当的代码后成为
程序代码:
#include <stdio.h>
int main()
{
    char *string;
    *string="I love china";   //注释1
    printf("%s\n",string);
    printf("%s\n",*string);   //注释2    
    return 0;
}

此代码在Digital Mars C/C++下会报错误:  from char *  to   char,  errorlevel 1.   说明了出现了不同类型的赋值操作.
而在MinGW3.4.5下只给出一条警告:  [Warning] assignment makes integer from pointer without a cast.英语不好,不知道如何翻译才能表达出准确的意思.大概意思就是不准确的赋值(从指针转换为整型).
另外,在注释2那个地方,系统会报内存不能读的错误.

把注释1那一行的*去掉,把注释2那一行的控制字符s换成c可以顺利通过. 第一个printf()输出字符串,第二个输出字符I.  

个人的理解是string代表的是整个的字符串,而*string是一个确切的地址,指向的是string的首字符.

代码测试环境:  WinXP+C-Free5.0.
2014-06-09 06:58
embed_xuel
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:58
帖 子:3845
专家分:11385
注 册:2011-9-13
收藏
得分:0 
回复 25 楼 vvvcuu
1,不管是64,65还是'A','B',取决于printf里面的格式化字符串是%s还是%d,数值是一样的,关键看你是如何使用这些数据,有句话这么说的,计算机世界里只有0和1。
2,不要把简单问题复杂化,运算符'*'是指针最基础的概念,不要混了

总有那身价贱的人给作业贴回复完整的代码
2014-06-09 07:09
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:0 
回复 26 楼 embed_xuel
其实我的问题是"为什么text.x就是字符串"?

代码测试环境:  WinXP+C-Free5.0.
2014-06-09 07:48
embed_xuel
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:58
帖 子:3845
专家分:11385
注 册:2011-9-13
收藏
得分:0 
回复 27 楼 vvvcuu
不管是64,65还是'A','B',取决于printf里面的格式化字符串是%s还是%d,数值是一样的,关键看你是如何使用这些数据,有句话这么说的,计算机世界里只有0和1。
你用printf和%s,自然就当字符串处理,如果用printf和%d,就当整型数处理。
char a = 'A';

printf("%c", a);
printf("%d", a);
这两个显示不一样吧。

把11楼,13楼,18楼连起来看

[ 本帖最后由 embed_xuel 于 2014-6-9 08:21 编辑 ]

总有那身价贱的人给作业贴回复完整的代码
2014-06-09 08:18
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 25 楼 vvvcuu
把13楼的代码修改一下解释你前面的问题:

程序代码:
#include <iostream>
#include <cstdlib>
#include <conio.h>

struct CustomData
{
    int x;
    char s[20];
};

int main(void)
{
    CustomData test = { (66 << 8) + 65, "Hello!" };
    printf_s("%d\n%s\n%s\n", (CustomData*)test.x, (CustomData*)&test.x, (CustomData*)test.s);

    unsigned char* p = (unsigned char*)&test;
    for (size_t index = 0; index < sizeof(test); ++index)
    {
        printf_s("%02x ", *(p + index));
    }
    putchar('\n');

    _getch();
    return EXIT_SUCCESS;
}


这个程序的输出是:
16961
AB
Hello!
41 42 00 00 48 65 6c 6c 6f 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00

最后一行是这个结构的内存影像。根据代码的结构体定义可知,前面4个字节是test.x,后面20个字节是test.s,数据是16进制的。对这个内存块,很明显看到前面3个字节正是一个以零(字符'\0'就是数值0)结尾的字符串。printf()函数当指定格式字符串为"%s%的时候,它假定后面的参数是一个cz字符串的地址,而我上面正是把地址(CustomData*)&test.x传给它,此时,printf()是不理会那个CustomData*类型转换的,它只按格式字符串的指示,将那个地址认作为某个字符串的入口,所以输出的就是字符串"AB",零字符后面的数据,如我们日常使用字符串所熟知的那样被忽略了。

但在第1行输出中,printf()函数的格式字符串是"%d",它指示函数认参数为整数,所以它取出一个整数(32位系统中是4字节)输出,这个整数的高位为'A'(65)、低位为'B'(66),如代码所示,(65 << 8) + 66,将65左移8位(即乘256)然后加上66。

第3行的输出,是把test.s的入口地址送给printf()的"%s"进行解析,这个入口地址是那块内存的(从序号0开始)第4字节,即0x48处,从这个字节开始,也是一个以'\0'结束的字符串。

记住:C字符串永远是从某个位置开始检索起,一直到找到'\0'为止,这个入口位置是可以随意变换的。字符串"ABCDE",可以从'A'开始,也可以从'B'开始!因此,上面整块结构体的内存也是一个字符串(24个字节的缓冲区,诸如像文件也是这样的数据块),它可以包含2个子字符串。

[ 本帖最后由 TonyDeng 于 2014-6-9 11:59 编辑 ]
收到的鲜花
  • vvvcuu2014-06-09 17:07 送鲜花  6朵   附言:怒赞.

授人以渔,不授人以鱼。
2014-06-09 11:35
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:0 
回复 29 楼 TonyDeng
终于明白了.  谢谢版主的回答.  版主的帖子向来技术性非常高的.  常拜读,常受益.

谢谢.


只是,  C板块,用的C++代码.  调试起来很纠结.  printf_s()函数在非MS开发环境下没有合适的函数代替,我都直接用的printf().

对于上面的代码, 最后的那段内存镜像仅仅输出了41 42 00 00,再后面的没有输出,不知道是不是因为用printf()的原因.

[ 本帖最后由 vvvcuu 于 2014-6-9 17:13 编辑 ]

代码测试环境:  WinXP+C-Free5.0.
2014-06-09 17:08
快速回复:结构体强制类型转换?
数据加载中...
 
   



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

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