1. 整型和枚举类型数据的转换
测试代码如下:
#include <stdio.h>

typedef enum _E_TYPE_T
{
    E_TYPE_1 = -1,
    E_TYPE_2,
    E_TYPE_3,
    E_TYPE_END
}E_TYPE_T;

int main(int argc, char* argv[])
{
    unsigned char ui1_value = 0;
    E_TYPE_T e_type = E_TYPE_1;
   
    printf("\nui1_value=%d,e_type=%d,e_type=%x\n", ui1_value, e_type, e_type);
   
    ui1_value = e_type;
    e_type = ui1_value;
   
    printf("\nui1_value=%d,e_type=%d,e_type=%x\n", ui1_value, e_type, e_type);
   
    return 0;
}

[~sh] gcc -o type_conversion_main type_conversion_main.c
[~sh] ./type_conversion_main

ui1_value=0,e_type=-1,e_type=ffffffff

ui1_value=255,e_type=255,e_type=ff

从实际运行结果来看,经过转换后的e_type的值显然不是程序员所期望的,这就会导致程序出错。
那应该要如何规避这个问题呢?大概有两种解法,
第一种就是不要定义unsigned char类型的ui1_value,而是定义一个signed char类型的i1_value,
第二种方法就是枚举类型中的成员从0开始计算,这样就可以避免有符号数和无符号数操作带来
的隐式数据转换,经过测试这两种方法均可行。

2. 整型和指针之间的转换
测试代码如下:
#include <stdio.h>

static int _get_data(int* pui4_value)
{
    *pui4_value = 0x12345678;
    return 0;
}

int main(int argc, char* argv[])
{
    char ui1_value_0 = 0;
    char ui1_value_1 = 0;
    char ui1_value_2 = 0;
   
    _get_data((int*)&ui1_value_2);
   
    printf("\ui1_value_0=%d,ui1_value_1=%d,ui1_value_2=%x\n", ui1_value_0, ui1_value_1, ui1_value_2);
   
    return 0;
}

[~sh] gcc -o type_conversion_main type_conversion_main.c
[~sh] ./type_conversion_main

ui1_value_0=34,ui1_value_1=56,ui1_value_2=78
[~sh]

这是怎么回事?明明只是去修改ui1_value_2,但是ui1_value_0,ui1_value_1的值怎么会变?
仔细的看,这个很有规律,原来是踩内存了。
原来int类型的数据会占用4个字节的内存,_get_data的参数是int*类型,所以调用_get_data后
它会回写四个字节的数据到指定的地址。
而ui1_value_2是char类型的数据,它只占用1个自己的内存空间,所以_get_data就会从ui1_value_2所处的地址
连续的写入4个字节的数据。
所以,我们知道,使用指针参数时一定要预留足够的空间以便于存储回传的数据,否则很容易就会踩内存;
而踩内存造成的后果是会出现大问题的。
此例的解法就是:定义一个int类型的变量ui4_value来接收_get_data的回传值,
经测试该方法可行。

3. signed和unsigned类型数据之间的转换
测试代码如下:
#include <stdio.h>

int main(int argc, char* argv[])
{
    signed char i1_value = -100;
    unsigned char ui1_value = 10;
    unsigned signed char sum = 0;
   
    sum = i1_value + ui1_value;
   
    printf("\nsum=%d\n", sum);
   
    return 0;
}

[~sh] gcc -o type_conversion_main type_conversion_main.c
[~sh] ./type_conversion_main

sum=166
[~sh]

这显然不是程序员所期望的结果。之所以出现这样的结果,是因为这涉及到数据转换中的一个隐式自动转换规则。
因为sum是unsigned char类型的数据,所以在做加法运算时i1_value被自动转换为unsigned char类型,
从而导致程序出现不预期的结果。
此例的解法就是定义sum为signed char类型。

结论:
1. 不同类型的数据如果需要相互转换,尽量要做到显示的转换,这也会增加代码的可读性;
2. 不同类型的数据之间的操作一定要特别特别小心;
3. 我们不是编译器开发者(实际上就算是编译器开发者也不见得了解编译器的所有特性),所以尽量不用编译器所赋予的隐含的技巧.

C语言中数据类型转换的学习的更多相关文章

  1. C语言中强制类型转换总结

    C语言中强制类型转换总结  ● 字符型变量的值实质上是一个8位的整数值,因此取值范围一般是-128-127,char型变量也可以加修饰符unsigned,则unsigned char 型变量的取值范围 ...

  2. JavaScript中数据类型转换总结

    JavaScript中数据类型转换总结 在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: var a = " ...

  3. HQL语句中数据类型转换,及hibernate中createQuery执行hql报错

    一.HQL语句中数据类型转换: 我们需要从数据库中取出序号最大的记录,想到的方法就是使用order by子句进行排序(desc倒序),然后取出第一个对象,可是当初设计数据库时(我们是在原来的数据库的基 ...

  4. Java中数据类型转换&基本类型变量和对象型变量

    1.Java的数据类型分为三大类 布尔型,字符型和数值型 其中数值型又分为整型和浮点型 2.Java的变量类型 布尔型 boolean 字符型 char 整型    byte,short,int,lo ...

  5. PHP中数据类型转换的三种方式

    PHP中数据类型转换的三种方式 PHP的数据类型转换属于强制转换,允许转换的PHP数据类型有: 1.(int).(integer):转换成整形2.(float).(double).(real):转换成 ...

  6. JS中数据类型转换

    JS中数据类型转换汇总 JS中的数据类型分为 [基本数据类型] 数字 number 字符串 string 布尔 boolean 空 null 未定义 undefined [引用数据类型] 对象 obj ...

  7. Arduino中数据类型转换 int转换为char 亲测好使,itoa()函数

    由于博主最近在做一个项目,需要采集不同传感器的数据,包括float型的HCHO,以及int型的PM2.5数据.但是最终向服务器上传的数据都得转换为char型才能发送,这是借鉴了一个github上面的实 ...

  8. C语言关于数据类型转换

    自动类型转换 自动类型转换就是编译器默默地.隐式地.偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生. 1) 将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,例如: ; ...

  9. C语言:数据类型转换 自动转换 强制转换

    数据类型转换就是将数据(变量.数值.表达式的结果等)从一种类型转换为另一种类型. 自动类型转换 自动类型转换就是编译器默默地.隐式地.偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生.1 ...

随机推荐

  1. Java小例子(学习整理)-----学生管理系统-控制台版

    1.功能介绍: 首先,这个小案例没有使用数据库,用集合的形式暂时保存数据,做测试! 功能: 增加学生信息 删除学生信息 修改学生信息 查询学生信息:  按照学号(精确查询)  按照姓名(模糊查询) 打 ...

  2. java_设计模式_组合模式_Composite Pattern(2016-08-12)

    概念: 组合模式(Composite Pattern)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 有时候又叫做部分-整体模式,它使我们树 ...

  3. 理解MySQL——索引与优化(转)

    写 在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页 面大小为4K,并存储100条记录.如果没有索引,查 ...

  4. 24种设计模式--抽象工厂模式【Abstract Factory Pattern】

    女娲造人,人是造出来了,世界是热闹了,可是低头一看,都是清一色的类型,缺少关爱.仇恨.喜怒哀乐等情绪,人类的生命太平淡了,女娲一想,猛然一拍脑袋,忘记给人类定义性别了,那怎么办?抹掉重来,然后就把人类 ...

  5. asp.net取HTML控件值

    asp.net取HTML控件值所有html表单里面的值控件,提交后都是以键值 key=value&key=value&……这样的形式提交给后台. radio也一样,会将选中的radio ...

  6. StartSSL免费SSL证书成功申请-HTTPS让访问网站更安全

    StartSSL免费SSL证书成功申请-HTTPS让访问网站更安全 一.StartSSL个人证书登录申请 1.StartSSL官网: 1.官方首页:http://www.startssl.com/ 2 ...

  7. 如何通过数据库修改WordPress后台登录密码

    大家是否有过因为忘记WordPress后台登陆密码的时候?其实WordPress后台登陆密码的找回或修改的方法有多种,比如通过邮箱重启密码,又或者通过主机控制面板进入数据库修改等等.本篇教程以GoDd ...

  8. HDUOJ Clear All of Them I 状压DP

    Clear All of Them I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 122768/62768 K (Java/Oth ...

  9. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  10. 【Java】servlet和servlet 容器

    servlet不是线程安全的,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,所以你的项目中如果只有一个servlet,那么web容器就只会创建一个实例 ...