变量和指针
数据类型
- 基本数据类型:整形、浮点型和字符型
- 构造数据类型:包括数组、结构、联合、枚举等。所谓构造数据类型,是指这种类型的数据,是由若干个基本数据类型的变量按特定的规律组合构造而成的。
整型
int
整型,占用 4 个字节,数的范围-2147483648 ~ 2147483647
unsigned int
无符号整型,占用 4 个字节,数的范围0 ~ 4294967295
long int
长整型,占用 4 个字节,数的范围-2147483648 ~ 2147483647
unsigned long int
无符号长整型,占用 4 个字节,数的范围0 ~ 4294967295
实型
float
浮点型,占用 4 字节,数的范围:-3.4*10的38次 ~ 3.4*10的38次
double
双精度型,占用 4 字节,数的范围:-1.7*10的308次 ~ 1.7*10的308次
long double
长双精度型,占用 10 字节,数的范围:-3.4*10的4932次 ~ 3.4*10的4932次
bool
逻辑型,占 1 一个字节, true & false
char
字符型,占一个字节
指针
- 变量若不设置初始值,变量的“初始值”是什么?
#include <iostream>
using namespace std;
int main()
{
int n;
cout << n << endl; // 100487205
return 0;
}
// 如果变量声明未赋值,则变量的内存单元中的值是一个随机的数值,在不同的机器上,不同环境上,单元中的内容是不同的
- 变量为什么要指定类型?类型信息用来做什么?不同类型差别是什么?
#include <iostream>
using namespace std;
int main()
{
int a = 2;
cout << "a 的值:" << a << endl; // 2
cout << "a/4 的值:" << a / 4 << endl; // 0
// 计算机认为这是整数相除,会把小数部分抹掉
// 解决: 把int改为float
return 0;
}
#include <iostream>
#include <string>
#include <complex>
using namespace std;
int main()
{
string str1 = "这是字符串1";
string str2 = "这是字符串2";
cout << "str1 的值:" << str1 << endl;
cout << "str2 的值:" << str2 << endl;
cout << "str1 + str2 的值:" << str1 + str2 << endl;
complex<int> c1(3, 4), c2(4, 5);
cout << "c1 的值:" << c1 << endl;
cout << "c2 的值:" << c2 << endl;
cout << "c1 + c2 的值:" << c1 + c2 << endl;
cout << "c1 * c2 的值:" << c1 * c2 << endl;
return 0;
}
/*
str1 的值:这是字符串1
str2 的值:这是字符串2
str1 + str2 的值:这是字符串1这是字符串2
c1 的值:(3,4)
c2 的值:(4,5)
c1 + c2 的值:(7,9)
c1 * c2 的值:(-8,31)
// 类型是计算机指导运算的
*/
- 变量存在哪里——变量内存单元地址
#include <iostream> // 包含库函数——预编译行,让 iostream 的内容包含到新建程序中
using namespace std;
int main()
{
int n;
float f;
double d = 1.23; // 0.0
char c = '*';
cout << "n 的地址:" << &n << endl;
cout << "f 的地址:" << &f << endl;
cout << "d 的地址:" << &d << endl;
cout << "c 的地址:" << &c << endl;
// &:取得变量内存单元地址的“操作符”
return 0;
}
/*
n 的地址:0x7ffeec9f5748
f 的地址:0x7ffeec9f5744
d 的地址:0x7ffeec9f5738
c 的地址:*�G�z��?hW���
d = 0.0 时
n 的地址:0x7ffee2345748
f 的地址:0x7ffee2345744
d 的地址:0x7ffee2345738
c 的地址:*
*/
- &是也给运算符,“取变量的地址”,所以&n 会返回变量 n 的内存单元地址;
- 对于内存单元地址,cout 会自动以 16 进制形式输出地址值。在这种形式输出结果中,前 2 个字符固定为 0x 或 0X;
- 在输出字符变量的内存地址时,cout 采取另外的特殊处理方式——不是输出变量的内存地址,而是输出内存单元储存的字符内容,且将相邻的后续内存单元也以字符形式输出出来,直至碰到一个内存为 0 的内存单元才停止。
- 变量地址(内存单元地址)是什么类型?
指针————存“变量地址”的变量
TYPE var 称为: var 是 TYPE 类型的指针变量 TYPE 类型的变量,其“地址”值,只能赋值给 TYPE 类型所对应的指针类型变量 即:用 TYPE定义的变量
#include <iostream>
using namespace std;
int main()
{
int n;
float f;
double d = 1.2;
char c = '*';
int* pn = &n; // 将n的内存地址存在pn里
float* pf = &f;
double* pd = &d;
char* pc = &c;
cout << "n 的地址:" << &n << endl;
cout << "f 的地址:" << &f << endl;
cout << "d 的地址:" << &d << endl;
cout << "c 的地址:" << &c << endl;
cout << "pn 的值:" << pn << endl;
cout << "pf 的值:" << pf << endl;
cout << "pd 的值:" << pd << endl;
cout << "pc 的值:" << pc << endl;
cout << "pn 的地址又在哪里:" << &pn << endl;
cout << "pf 的地址又在哪里:" << &pf << endl;
cout << "pd 的地址又在哪里:" << &pd << endl;
cout << "pc 的地址又在哪里:" << &pc << endl;
// 这里输出变量 pn pf pd pc 的内存单元值
return 0;
}
/*
n 的地址:0x7ffee61c2748
f 的地址:0x7ffee61c2744
d 的地址:0x7ffee61c2738
c 的地址:*333333�?h'��
pn 的值:0x7ffee61c2748
pf 的值:0x7ffee61c2744
pd 的值:0x7ffee61c2738
pc 的值:*333333�?h'��
pn 的地址又在哪里:0x7ffee61c2728
pf 的地址又在哪里:0x7ffee61c2720
pd 的地址又在哪里:0x7ffee61c2718
pc 的地址又在哪里:0x7ffee61c2710
*/
- 对变量地址对应的内存单元的读写操作如何进行?
#include <iostream>
using namespace std;
int main()
{
int n;
float f;
double d = 1.2;
char c = '*';
int* pn = &n;
float* pf = &f;
double* pd = &d;
char* pc = &c;
*pn = 999; // 写
*pf = 888;
*pd = 777;
*pc = 'A';
cout << "pn:" << pn << ",pn 的地址:" << &pn << endl;
cout << "pf:" << pf << ",pf 的地址:" << &pf << endl;
cout << "pd:" << pd << ",pd 的地址:" << &pd << endl;
cout << "pc:" << pc << ",pc 的地址:" << &pc << endl;
cout << "n 的地址:" << pn << ",*pn 的值:" << *pn << endl; // 读
// *pn 从 pn 中存储的地址值所对应的内存单元中,读取内存单元的内容
cout << "n 的值:" << n << endl;
return 0;
}
/*
pn:0x7ffee2178748,pn 的地址:0x7ffee2178728
pf:0x7ffee2178744,pf 的地址:0x7ffee2178720
pd:0x7ffee2178738,pd 的地址:0x7ffee2178718
pc:A,pc 的地址:0x7ffee2178710
n 的地址:999
*/
// *pn 就是去获得该指针变量的单元
// 对指针地址赋值就是对保存在该地址上的变量重新赋值
测试例子:
#include <iostream>
using namespace std;
int main()
{
int a = 100;
int *ap = &a;
printf("%p\n", &a); // 输出:0x7ffee5b68748 输出的是变量a的地址
printf("%p\n", ap); // 输出:0x7ffee5b68748 输出的指针的值,与的一个输出相同,也就是说指针的值是指针所指向的变量的地址
printf("%d\n", *ap); // 输出:100 *号是获取指针变量所指向的地址所存放的内容的操作
printf("%p\n", &ap); // 输出:0x7ffee5b68740 取得指针变量ap的地址
printf("%p\n", &*ap); // 输出:0x7ffee5b68748 *ap指向的是变量a的内容,而&*ap即是获取变量a的内容的地址
return 0;
}
- 变量地址(内存单元地址)的加减操作
#include <iostream>
using namespace std;
int main()
{
int n1 = 12, n2 = 87;
char c1 = '9', c2 = 'B';
// 获取变量的值和地址
cout << "n1的值:" << n1 << ",n1的地址:" << &n1 << endl;
cout << "n2的值:" << n2 << ",n2的地址:" << &n2 << endl;
cout << "c1的值:" << c1 << ",c1的地址:" << &c1 << endl;
cout << "c2的值:" << c2 << ",c2的地址:" << &c2 << endl;
// 获取变量地址
int* pn = &n1;
char* pc = &c1;
cout << "pn的值:" << pn << endl;
cout << "pn + 1 = " << pn + 1 << endl;
cout << "pn - 1 = " << pn - 1 << endl;
cout << "pc的值:" << pc << endl;
cout << "pc + 1 = " << pc + 1 << endl;
cout << "pc - 1 = " << pc - 1 << endl;
return 0;
}
/*
n1的值:12,n1的地址:0x7ffeef56b748
n2的值:87,n2的地址:0x7ffeef56b744
c1的值:9,c1的地址:9W
c2的值:B,c2的地址:B9W
pn的值:0x7ffee17b8748
pn + 1 = 0x7ffee17b874c 16进制8+4=>c
pn - 1 = 0x7ffee17b8744 16进制8-4=>4
pc的值:9W
pc + 1 = W
pc - 1 = B9W
*/
- 对于指向整数单元的整数指针,对它进行加减操作,加的减的字节数是一个 int 占的大小的字节数
T* p = &var
p + 1 => value 0f p + sizeof(T)
p - 1 => value 0f p - sizeof(T)
- 变量有什么用途?什么时候用?如何使用变量?怎么命名?
计算思维:
#include <iostream>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
cout << a + b << endl;
}
实例问题
A B C D 四个人其中一个人做好事,然后 A 说:不是我 B 说:是 C C 说:是 D D 说:C 胡说 其中,四个人只有一人说的是假话,其他三人是真话,请问,谁做的好事?
关系运算符: != 和 ==,表示让计算机算一下,俩侧内容是否符合这一关系运算符的意义:
- 若符合,则计算结果为“真”
- 若不符合,则计算结果为“假”
#include <iostream>
using namespace std;
int main()
{
int count = 0;
char good_man;
good_man = 'D'; // A B C D 手动改变 A B C D 的值,当然也可以多加if语句实现,这里为了减少篇幅,手动改了~
if(good_man != 'A') // A 说
count++;
if(good_man == 'C') // B 说
count++;
if(good_man == 'D') // C 说
count++;
if(good_man != 'D') // D 说
count++;
if(count == 3)
cout << count << endl;
else
cout << "else:" << count << endl;
}
谁是嫌疑犯问题
有 ABCDEF 6 个人,其中:(用 0 表示没有参与作案, 1 表示参与作案) A B 至少有一人作案 => (A == 1) || (B == 1) A E F 中至少有 2 人作案 => (A == 1) && (E == 1) || (A == 1) && (F == 1) || (E == 1) && (F == 1) A D 不可能是同案犯 => !((A == 1) && (D == 1)) B C 或同时作案,或与本案无关 => (B == 1) && (C == 1) || ((B == 0) && (C == 0) C D 中有且仅有一人作案 => (C == 1) && (D == 0) || (C == 0) && (D == 1) 如果 D 没有参与作案,E 也没有作案 => (D == 0) && (F == 0) || (D == 1)
解决:枚举
:
#include <iostream>
using namespace std;
int main()
{
int A, B, C, D, E, F;
bool found = false; // 判断是否找到答案,终止遍历
for(A = 0; A <= 1 && !found; A++)
for(B = 0; B <= 1 && !found; B++)
for(C = 0; C <= 1 && !found; C++)
for(D = 0; D <= 1 && !found; D++)
for(E = 0; E <= 1 && !found; E++)
for(F = 0; F <= 1 && !found; F++)
{
bool b1 = (A == 1) || (B == 1);
bool b2 = ((A == 1) && (E == 1)) || ((A == 1) && (F == 1)) || ((E == 1) && (F == 1));
bool b3 = !((A == 1) && (D == 1));
bool b4 = ((B == 1) && (C == 1)) || ((B == 0) && (C == 0));
bool b5 = ((C == 1) && (D == 0)) || ((C == 0) && (D == 1));
bool b6 = ((D == 0) && (F == 0)) || (D == 1);
bool all = b1 && b2 && b3 && b4 && b5 && b6;
if(all)
{
cout << A << B << C << D << E << F << endl;
found = true;
}
}
}
// 111010
用二进制枚举
用
(000000)
枚举到(111111)
A | B | C | D | E | F |
---|---|---|---|---|---|
0 | 1 | 1 | 0 | 1 | 0 |
二进制运算
表示 | 概念 | 例子 | 解释 | ||
---|---|---|---|---|---|
& | 按位与 | (0101)&(1100)=(0100) | &1 保持原来的值,&0 都会变成 0 通过&一个特定值,可以设置某些位为 1 其他位不变 有 0 为 0,都 1 为 1 | ||
` | ` | 按位或 | `(0101) | (1100)=(1101)` | |1 都会变成 1,|0 保持原来的值 通过|一个特定值,可以设置某些位为 1 其他位不变 有 1 为 1,都 0 为 0 |
^ | 按位异或 | (0101)^(1100)=(1001) | ^1会变,^0保持原来的值 通过^一个特定值,可以设置某些位为 1 其他位不变 不同为 1,相同为 0 | ||
~ | 按位取反 | ~(01)=(10) | 所有位都变化,按位取反 | ||
>> | 往右移位 | 00011010 >> 2 = 00000110 | 所有右移,高位重复 | ||
<< | 往左移位 | 00011010 << 2 = 0110 1000 | 所有左移,低位补 0 |
// 左移n位,相当于乘以2的n次方
/* 每位是否作案:
A = (i >> 5) & 1;
B = (i >> 4) & 1;
C = (i >> 3) & 1;
D = (i >> 2) & 1;
E = (i >> 1) & 1;
F = i & 1;
*/
#include <iostream>
using namespace std;
int main()
{
for(int i = 0; i < ( 1 << 6); i++)
{
int A = (i >> 5) & 1;
int B = (i >> 4) & 1;
int C = (i >> 3) & 1;
int D = (i >> 2) & 1;
int E = (i >> 1) & 1;
int F = i & 1;
bool b1 = (A == 1) || (B == 1);
bool b2 = ((A == 1) && (E == 1)) || ((A == 1) && (F == 1)) || ((E == 1) && (F == 1));
bool b3 = !((A == 1) && (D == 1));
bool b4 = ((B == 1) && (C == 1)) || ((B == 0) && (C == 0));
bool b5 = ((C == 1) && (D == 0)) || ((C == 0) && (D == 1));
bool b6 = ((D == 0) && (F == 0)) || (D == 1);
bool all = b1 && b2 && b3 && b4 && b5 && b6;
if(all)
{
cout << A << B << C << D << E << F << endl;
break;
}
}
}