提示:本文为学习记录,若有错误,请联系作者,谦虚受教。
前言
Raindrops are very gentle, there is romance in the world
一、typedef
程序中使用到typedef,回顾此关键字的使用。
- 定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象
- 用在旧的C的代码中,帮助struct。以前的代码中,声明struct新对象时,必须要带上struct,即形式为: struct 结构名 对象名
但是加上typedef的时候,声明struct新对象的时候,只需要 “结构名 对象名”。 - 用typedef来定义与平台无关的类型。
比如定义一个叫 ABC 的浮点类型,在目标平台一上,让它表示最高精度的类型为:
typedef long double ABC;
在不支持 long double 的平台二上,改为:
typedef double ABC; - 为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化版。举例:
原声明:int *(a[5])(int, char);
变量名为a,直接用一个新别名pFun替换a就可以了:
typedef int *(pFun)(int, char);
原声明的最简化版:
pFun a[5];
二、结构体
读取设备号的函数中,涉及到结构体的使用,对此回顾总结结构体的定义及使用。
1.结构体声明及使用
声明结构体的方式:
-
使用关键字 struct
-
尽管结构体可以包含成员函数,但它们很少这样做。所以,通常情况下结构体声明只会声明成员变量。
-
结构体的成员则默认为 public。
-
语法:struct 结构体名{结构体成员列表}
通过结构体创建变量的方式:
1、struct 结构体 变量名
2、struct 结构体名 变量名={成员值1,成员值2.。。}
3、定义结构体时顺便创建变量
语法:struct 结构体名{结构体成员列表}
通过结构体创建变量的方式:
1、struct结构体 变量名
2、struct结构体名 变量名={成员值1,成员值2.。。}
3、定义结构体时顺便创建变量
第一种
#include<iostream>
#include<string>
using namespace std;
//创建学生的数据类型;学生包括姓名、年龄、分数
//自定义的数据类型,一些类型集合组成的一个类型
//语法: struct 类型名称{成员列表}
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}
//通过学生类型创建具体学生
int main()
{
//struct student s1
struct student s1; //struct关键字可以省略
//给s1属性赋值,通过 . 访问结构体变量中的属性
s1.name="张三";
s1.age=18;
s1.score=100;
cout<<"姓名"<<s1.name<<"年龄"<<s1.age<<"分数"<<s1.score<<endl;
cout<<"姓名"<<s1.name<<"年龄"<<s1.age<<"分数"<<s1.score<<endl;
system("pause");
return 0;
}
第二种
#include<iostream>
#include<string>
using namespace std;
//struct student s2={....}
struct student s2={
"李四",19,100};
第三种
#include<iostream>
#include<string>
using namespace std;
//定义结构体时顺便创建变量
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3;//顺便创建结构体变量
int main()
{
s1.name="王五";
s1.age=18;
s1.score=100;
cout<<"姓名"<<s1.name<<"年龄"<<s1.age<<"分数"<<s1.score<<endl;
system("pause");
return 0;
}
总结:
1、定义结构体的关键字是struct 不可省略。
2、创建结构体变量时,关键字struct可以省略。
3、结构体变量利用操作符“.”访问成员,就是 “.” 点运算符
2.结构体大小
我们都知道:
char :1个字节
short :2个字节
int :4个字节
float :4个字节
long :4个字节
double :8个字节
偏移量:
类型 对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
Char 偏移量必须为sizeof(char)即1的倍数
Short 偏移量必须为sizeof(short)即2的倍数
int 偏移量必须为sizeof(int)即4的倍数
float 偏移量必须为sizeof(float)即4的倍数
double 偏移量必须为sizeof(double)即8的倍数
struct stru{
char a; //第一个成员a的偏移量为0
int b; //第二个成员b的偏移量是第一个成员的偏移量加上第一个成员的大小(0+1=1,但是必须是第二个变量类型长度4的倍数,即为4)
float c; //第三个成员c的偏移量是第二个成员的偏移量加上第二个成员的大小(4+4=8,但是必须是第三个变量类型长度4的倍数,即为8)
double d; //第四个成员d的偏移量是第三个成员的偏移量加上第三个成员的大小(8+4=12,但是必须是第四个变量类型长度8的倍数,即为16)
};
//最后计算结构体大小等于最后一个成员(第四个)的偏移量(16)加上最后一个成员的大小(8)。
//即16+8(double)=24
//另外结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。
//大于等于24并且1,4,4,8的公倍数------>24
(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。
3.例子
这里声明了结构体变量DEVICE_INFO,我们下面所使用到的就是这个结构体中的
char byFirmwareVer[8],定义存放设备号的八字节的数组。(一个字节等于八位,二者具体关系点击:网址)
//结构体
typedef struct
{
char byPCBAVer[8]; //ASCII
char byName[16]; //product name, ASCII code
char byDescription[64]; //description, ASCII code
uint u32DeviceID; //device ID
char byFirmwareVer[8]; //V1.00, ASCII code
}DEVICE_INFO;
二、读设备号
1.第一种方法
返回的是字符串,利用字符串数组存储接收的数据。
代码如下(示例):
QString HIOKI3238::DMM_ReadDeviceID(QString &strInfo)
{
QString DeviceID;
int IDLen;
uchar sendBuf[] = {
0xFE,0x3A,0x00,0x00,0x00};
ushort sLen = sizeof (sendBuf)/sizeof (sendBuf[0]);
uchar rcvBuf[100] = {
};
ushort rcvLen=15;
uchar ID;
int resLen = SendAnRead(sendBuf,sLen,rcvBuf,rcvLen,1000);
if(rcvBuf[0] != 0x46 || rcvBuf[1] != 0x45 ||rcvBuf[2] != 0x42 )
{
return 0;
}
else
{
for(int i=0; i<8;i++)
{
strInfo += char(rcvBuf[i+4]);
}
return strInfo;
}
}
2.第二种方法
利用指针数组,访问结构体中char byFirmwareVer[i]数组
代码如下(示例):
//状态
#define STATE_ON 1
#define STATE_OFF 0
int HIOKI3238::GetInfoData(DEVICE_INFO *DeviceInfo)
{
QString DeviceID;
uchar sendBuf[] = {
0xFE,0x3A,0x00,0x00,0x00};
ushort sLen = sizeof (sendBuf)/sizeof (sendBuf[0]);
uchar rcvBuf[100] = {
0};
ushort rcvLen=sizeof (DEVICE_INFO)+2;
int resLen = SendAnRead(sendBuf,sLen,rcvBuf,rcvLen,1000);
if(resLen > 0)
{
if(rcvBuf[0] != 0xFE || rcvBuf[1] != 0x3A ||rcvBuf[2] != 0x00 )
{
return STATE_OFF;
}
else
{
int index = 4;
for(int i =0 ;i<8; i++)
{
DeviceInfo->byFirmwareVer[i] = rcvBuf[index++];
}
return STATE_ON ;
}
}
else
{
return STATE_OFF;
}
}
总结
善于总结,多进一步。