//************** 强制类型转换实用技巧(地址类型转换)******************
//(A)将long型变量a(值:0x12345678)的第3个字节(值:0x56)赋给char型变量b。
// (B) 将数组的4个字节拼成1个long型变量
// (C) 将数组的4个字节转换成2个整数
// (D) 将数组的4个字节转换成1个float小数
// (E) 将float型变量各个字节取出
// (F) 将void型指针强制转换成任意类型指针
#include "STC15W4K.H" // 注意宏定义语句后面无分号
unsigned long a;
unsigned char b;
int c,d;
unsigned char f1,f2;
float f;
void *p; // 定义指向类型不明确的数据的指针(指针就是数据存放的地址)
unsigned char array[]={0x11,0x22,0x33,0x44};
struct stru
{
int a;
int b;
};
struct stru *pstru; //定义指向结构体的指针变量
void main()
{
// ******************** 长 整 型 转 字 符 型 ******************
a=0x12345678;
b=((unsigned char *)&a)[2]; //执行后b=0x56
// 解释:长整型地址转字符型地址,(地址)[2],()是括号运算符,即先计算括号里面的内容,
// 地址[2],表示取出当前地址加2地址中的内容。
// *********************** 数 组 转 长 整 型 *********************
a=*((unsigned long *)array); //执行后a=0x11223344 (数组的名字就代表数组首地址)
// 解释:数组型地址转长整型地址,*(地址),()是括号运算符,即先计算括号里面的内容,
// * 是取内容运算符。
// *********************** 数 组 转 结 构 体 *********************
pstru=(struct stru *)array;
//解释:数组型地址转结构体地址。pstru本来就是已定义好的专门存放地址的变量,即指针
// 变量
c=pstru->a; //执行后c=0x1122
d=pstru->b; //执行后d=0x3344
// 解释:使用"结构体变量地址->成员名"或"结构体变量名->成员名"的方法都可以访问结
// 构体中的数据
// *********************** 数 组 转 浮 点 型 *********************
f=*((float *)array); //执行后f=0x11223344,对应小数是1.279534e-028
//解释:数组型地址转浮点型地址。
// *********************** 数 组 转 字 符 型 *********************
p=array;
//解释:数组型地址转空类型地址。
b=((unsigned char *)p)[0]; //执行后b=0x11
// *********************** 浮 点 型 转 字 符 型 ********************
f1=((unsigned char *)&f)[0]; //执行后f1=0x11
//解释:浮点型地址转字符型地址。
//或f1=*(((unsigned char *)&f)+0); //执行后f1=0x11
f2=((unsigned char *)&f)[1]; //执行后f2=0x22
((unsigned char *)&f)[0] ^= 0x80; // 将4字节浮点数的符号位取反,注意^=数
//写不要错误
// ******************* void 型 指 针 转 任 意 类 型 指 针*************
p= array;
f1= ((unsigned char *)p)[0]; // 执行后f1=0x11,访问数组中第1个字节的内容
}
学到一个东西:一个变量比如 char a,
对a取地址后 &a的类型为(unsigned char *),
此时( (unsigned char *)a)[2]
(举个例子而已,不要较真)
地址[2],表示取出当前地址加2地址中的内容
unsigned char a _at_ 0x0001;
unsigned char b[]={0,1,2,3,4,5,6,7,8,9};
unsigned char c[][2]={{0,1},{2,3},{4,5}};
void main()
{
a=b[3]; // a=3
b[2]=100; // b= {0,1,100,3,4,5,6,7,8,9};
*(b+2)=200; // b= {0,1,200,3,4,5,6,7,8,9};
b[-1]=4; // a=4;
((unsigned char *)(((unsigned long *)b)+1))[0]=250;
// b={0,1,200,3,250,5,6,7,8,9};
while(1);
}
特别注意:
((unsigned char *)(((unsigned long *)b)+1))[0]=250;
// b={0,1,200,3,250,5,6,7,8,9};
地址是long+1 也就是第5个字节,然后选择第五为250
还有一个有关大小端的强制转换。。。。<大小端详细看这里>
上代码
keil 大端模式下
#include <stdio.h>
#include <reg52.h>
void main()
{
unsigned char b, c;
unsigned long a;
while(1)
{
a = 0x12345678;
b = (unsigned char)a; //0x78
c = ((unsigned char *)&a)[0]; //0x12
}
}
CB小端模式下:
#include <stdio.h>
#include <reg52.h>
void main()
{
unsigned char b, c;
unsigned long a;
while(1)
{
a = 0x12345678;
b = (unsigned char)a; //0x78
c = ((unsigned char *)&a)[0]; //0x78
}
}
总结一下:
当不涉及地址时,强制转化就是我们平时所理解的,直接取最低字节就行了。
当涉及地址时候,务必要考虑低地址存的是高字节(大端)还是低字节(小端)!