跳到主要内容

变量和指针

数据类型

  • 基本数据类型:整形、浮点型和字符型
  • 构造数据类型:包括数组、结构、联合、枚举等。所谓构造数据类型,是指这种类型的数据,是由若干个基本数据类型的变量按特定的规律组合构造而成的。

整型

  1. int整型,占用 4 个字节,数的范围-2147483648 ~ 2147483647
  2. unsigned int无符号整型,占用 4 个字节,数的范围0 ~ 4294967295
  3. long int长整型,占用 4 个字节,数的范围-2147483648 ~ 2147483647
  4. unsigned long int无符号长整型,占用 4 个字节,数的范围0 ~ 4294967295

实型

  1. float 浮点型,占用 4 字节,数的范围:-3.4*10的38次 ~ 3.4*10的38次
  2. double 双精度型,占用 4 字节,数的范围:-1.7*10的308次 ~ 1.7*10的308次
  3. long double 长双精度型,占用 10 字节,数的范围:-3.4*10的4932次 ~ 3.4*10的4932次

bool

逻辑型,占 1 一个字节, true & false

char

字符型,占一个字节

指针

  1. 变量若不设置初始值,变量的“初始值”是什么?
#include <iostream>
using namespace std;

int main()
{
int n;
cout << n << endl; // 100487205
return 0;
}
// 如果变量声明未赋值,则变量的内存单元中的值是一个随机的数值,在不同的机器上,不同环境上,单元中的内容是不同的
  1. 变量为什么要指定类型?类型信息用来做什么?不同类型差别是什么?
#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)
// 类型是计算机指导运算的
*/
  1. 变量存在哪里——变量内存单元地址
#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 的内存单元才停止。
  1. 变量地址(内存单元地址)是什么类型?

指针————存“变量地址”的变量

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
*/
  1. 对变量地址对应的内存单元的读写操作如何进行?
#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;
}
  1. 变量地址(内存单元地址)的加减操作
#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)
  1. 变量有什么用途?什么时候用?如何使用变量?怎么命名?

计算思维:

#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)

ABCDEF
011010

二进制运算

表示概念例子解释
&按位与(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;
}
}
}