本章学习目标:
1.bool类型
2.const限定符
3.const与#define
4.结构体内存对齐
1.1 bool类型
bool类型也称为逻辑型,其取值为true(逻辑真)和false(逻辑假),存储字节在不同编译系统中可能有所不同,Qt中为1个字节。
声明方式如下,可以将bool类型当作整数用,true一般为1,false为0
//此段代码为QtCreator开发工具,创建 Qt Console Application得到的main函数代码
//其中添加了定义bool变量以及读取bool变量大小的代码
#include <QCoreApplication>
#include <iostream>
#include <stdio.h>
using namespace::std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
bool testBool = true; // 创建bool变量
cout <<sizeof (testBool)<< endl; // 读取bool大小 输出结果为 1
return a.exec();
}
注意,将其它类型的值转为bool值时,非零值转换为true,零值转为false。
//此段代码为QtCreator开发工具,创建 Qt Console Application得到的main函数代码
#include <QCoreApplication>
#include <iostream>
#include <stdio.h>
using namespace::std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
bool testBool = bool (-1);
cout << testBool << endl; //输出结果 testBool = 1
testBool = bool (0);
cout << testBool << endl; //输出结果 testBool = 0
return a.exec();
}
1.2 const 限定符
const 是修饰变量的标识符,经过const修饰的变量就不能再改变了。所以也将const修饰的变量称为常变量。
定义的一般形式:
const 数据类型 常量名 = 常量值;
数据类型 const 常量名 = 常量值;
例如:const float PI = 3.14159;
注意:常量在定义时必须初始化,常量在初始化后,不允许再被赋值。
#include <QCoreApplication>
#include <iostream>
using namespace::std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//const常变量,常变量的定义一定要初始化。
//const int a; 这是一个错误写法,没有初始化
const int aa = 10;
// aa = 20; 这是个错误写法,常量不能重新被赋值
//创建一个常量指针
const int *p; //const 在 * 左边,*p是常量,*p指向的值不能改变
int b = 22;
p = &aa; // 将aa的地址赋值给p指针
//*p = 22; 这是一个错误写法, // 取出p指针的值
//const在*右边
//int * const p2; 这是一种错误写法,p2为常量,在定义时先要赋值
int * const p2 = &b;
int c = 100;
// p2 = &c; 这是一个错误写法
*p2 = 200;
cout << b<< endl; //会发现b的值也发生了变化。
return a.exec();
}
1.3 const与#define
const与#define的主要区别有以下几点:
1.const定义的常量有类型,而#define定义的没有类型,编译可以对前者进行类型安全检查,后者仅仅是做一个简单替换
2.const定义的常量在编译时分配内存,而#define定义的常量是在预编译时进行替换,不分配内存。
3.作用域不同,const定义的常量的作用域为该变量的作用域范围,而#define定义的常量作用域为它定义点到程序结束,当然也可以在某个地方用#undef取消
#include <QCoreApplication>
#include <iostream>
using namespace::std;
#define STR(a) #a //#a是将a转为string
#define CAT(a,b) a##b //a##b 是将ab合并起来
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int xy = 200;
cout << STR(ABCD) << endl;
cout << CAT(x,y) << endl;
return a.exec();
}
注意:定义常量还可以用enum,尽量用const、enum替换#define定义常量
//Effective C++ 3rd的一个例子
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))
int a = 5;
int b = 0;
CALL_WITH_MAX(++a,b) //a被累加两次
CALL_WITH_MAX(++a,b + 10) //a被累加一次
1.4 结构体内存对齐
什么是内存对齐?
编译器为每个“数据单元”安排在某个合适的位置上。c,c++语言非常灵活,它允许你干涉“内存对齐”
为什么要对齐?
因为考虑到性能,在对齐的地址上访问数据快。
如何对齐?
第一步:第一个数据成员放在offset为0的位置,第二步:其他成员对齐至 #pragma pack 所指定的值的整数倍位置。
注意:整个结构体总大小对齐至各个成员中最大对齐数的整数倍。
#include <QCoreApplication>
#include <iostream>
#include <stdio.h>
using namespace::std;
#pragma pack(4) //设置内存对齐数
struct Test
{
char a;
double b;
char c;
};
//结构体中,第一个成员与结构体偏移量为0 &test == &test.a
//结构体中其他成员要对齐到对齐数的整数倍的地址
//结构体总大小为对齐数的整数倍
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Test test;
char * p = (char *)&test;
cout << p <<endl;
printf("p = %p\n",p);
p = &test.a;
cout << p <<endl;
printf("p = %p\n",p);
return a.exec();
}