介绍数据类型

操作系统根据数据类型分配内存空间,同一种数据类型才可以进行计算,如:
合法的运算:

55+15 //  legal C++ expression

非法的运算:

55 + "John" // illegal

数字类型的有两种类型:
整型,如:710
浮点型,如:3.145.67

字符串是一个数字、字符、符号的集合。使用双引号来标记,如:"hello"

字符使用单引号来标记,如:'A'

Boolean 类型只有两个可能的值:truefalse

整型

整型一般默认 4 个字节的存储空间。

使用 int 来定义:

int a = 42;

带符号型,可以定义正数和负数,一般不写默认 int 就是带符号型:

signed int a;

无符号型,只能定义正数型:

unsigned int a;

short 型,一般默认空间占用大小,就是 2 个字节:

short int a;

long 型,2倍默认空间大小:

long int a;

浮点型

有三种浮点类型:float, double, 和 long double。浮点型都是 signed 带符号型的。

一般情况下,float 型 4 个字节,double 型 8 个字节,long double 型 16 个字节。

使用 float 来定义:

float a = 3.14;

字符串

string 字符串类型是一个字符、数字和符号的集合,使用双引号来标记。

使用 string 定义变量,需要使用 <string> 库:

#include <string>
using namespace std;

int main() {
    string test = "hello";
    return 0;
}

注意:<string> 库包含在 <iostream> 库中,所以如果已经引用来 <iostream> 就不需要再引用 <string> 了。

char 类型

char 类型包含了 1 个字节的整数,但是解释器会将这个整数解释为 ASCII 码对应字符。使用单引号来标记,如:

char a = 'a';

变量定义规则

所有变量的定义需要遵守以下规则:

  • 变量名首位必须是一个字母或下划线 _
  • 首字符之后的可以使用字母或数字,不能使用特殊字符或空格

一般有两种常用的定义方法

  • 首字母及每个单词的首字符大写,如: BlankWord
  • 首字母小写后续的每个单词首字符大写,如:blankWord

所有的变量名都是区分大小写的,如:helloword 和 HelloWord 是两个变量。

数组

数组是一个同一种数据类型变量的集合体,只需要一次就可以定义多个同一种变量类型的变量。如:

int a[5] = {1, 2, 5, 7, 8};

变量名后方括号[]定义数组内变量个数,大括号{}内包含数组内元素实际值,使用逗号,分隔各个元素。注意大括号内的元素个数不能超过数组变量定义的个数。

也可以在定义时不说明元素个数:

int a[] = {1, 3, 7, 9};

会自动创建足够存储内部元素的数组。

数组内每个元素都有一个 index 索引,从 0 开始,所以数组内第一个元素索引为 0,第二个为 1。使用索引号可以访问对应元素:

int b[] = {11, 45, 62, 70, 88};

cout << b[0] << endl;
// Outputs 11

cout<< b[3] << endl;
// Outputs 70

如果需要逐个访问数组内元素,可以使用 loop 循环来实现:

int myArr[5];

for(int x=0; x<5; x++) {
  myArr[x] = 42;
}

多维数组

以上是单维数组的定义,也可以定义多维数组,如定义一个二位数组:

int a[3][4];

想象这个数组为一个矩阵,有三行,每行 4 个元素:
DownloadFile.png

定义多维数组定义元素需要每行在一个大括号下单独定义:

int x[2][3] = {
  {2, 3, 4}, // 1st row
  {8, 9, 10} // 2nd row
};

也可以在一行内定义:

int x[2][3] = {{2, 3, 4}, {8, 9, 10}};

使用行号和列号来定位一个元素:

int x[2][3] = {{2, 3, 4}, {8, 9, 10}};
cout << x[0][2] << endl;

//Outputs 4

指针

每个变量都存储在内存单元内,每个内存空间都有地址。这个内存地址可以使用地址查询符&来查询,如:

int score = 5;
cout << &score << endl;

//Outputs "0x29fee8"

返回的地址就是存储变量 score 的值的地址空间。

一个 pointer 指针就是一个存储某个变量所在内存地址的变量。指针类型可以使某些任务实现更加方便,某些任务,如动态内存分配则必须使用指针来实现。

不同类型的指针变量的唯一区别就是其所在内存地址的数据类型的不同。

和其他变量类型一样,定义指针变量需要申明类型。使用星号* 来表示是指针类型的变量。

int *ip;  // pointer to an integer
double *dp;   // pointer to a double
float *fp;  // pointer to a float
char *ch;  // pointer to a character

星号* 可以放在数据类型旁边或者变量旁边或者单独写在中间。

我们可以将一个地址赋给指针变量:

int score = 5;
int *scorePtr;
scorePtr = &score;

cout << scorePtr << endl;

//Outputs "0x29fee8"

scorePtr 的值就是 score 变量的内存地址。

有两种指针的运算器:

  • 地址查询符&,返回操作数所在内存地址 referencing
  • 数据查询符*,返回操作数的内存地址下的数据 dereferencing

例如:

int var = 50;
int  *p;
p = &var;

cout << var << endl;
// Outputs 50 (the value of var)

cout << p << endl;
// Outputs 0x29fee8 (var's memory location)

cout << *p << endl;
/* Outputs 50 (the value of the variable
 stored in the pointer p) */

定义指针类型变量时候的星号* 只是用来表明此变量为指针类型变量,不要和内存查询符混淆。

数据查询符* 指针指向的变量的 alias,例如:

int x = 5;
int *p = &x;

x = x + 4;
x = *p + 4;
*p = *p + 4;

P 是 x 的指针,以上示例的三种运算结果都是一样的,都是将变量 x 的值进行计算。我们可以通过定义变量的指针来操作变量值。

静态内存和动态内存

理解动态内存的工作机制对于开发有很大帮助。再 c++ 中内存被分为两种类型:

  • the stack 静态内存空间:所有的本地变量占用静态内存空间
  • the heap 动态内存空间:再程序运行时动态进行分配的空间,默认不占用

很多情况下,提前并不知道一个定义的变量需要多少空间来存储信息需要在运行时动态请求内存空间。可以使用 new 操作符来定义一个变量使用 heap 方式再运行时动态分配内存空间,并返回分配的地址,例如:

new int;

以上定义一个使用 heap 方式分配一个足够存储 int 类型的内存空间,并返回这个地址。分配的地址可以存储在一个指针中,可以在后续中使用:

int *p = new int;
*p = 5;

以上请求了一个动态内存来存储一个 int 类型数据,然后在这个地址存储值为 5。注意指针 p 变量存储在 stack 静态内存中,且其值为 heap 动态内存分配的 int 型数据的地址,结果 5 是存储在 heap 动态内存中的。

本地静态内存 stack 下的变量,内存管理是自动进行的不需要手动干预,使用 heap 方式动态分配的内存空间需要手动干预操作,当不再需要动态内存空间的数据时使用 delete 操作符来释放空间。

示例:

int *p = new int; // request memory
*p = 5; // store value

cout << *p << endl; // use value

delete p; // free up the memory

忘记释放使用 new 请求的动态内存空间会导致内存泄漏问题,因为在程序关闭时才会释放空间。

注意 delete 操作的是指针类型。并且释放的只是 heap 动态内存,指针本身是存储在 stack 中的。当内存释放后,指针不指向某个内存地址,次时这个指针叫做:dangling pointers 悬浮指针。可以重新让这个指针指向内存地址:

int *p = new int; // request memory
*p = 5; // store value

delete p; // free up the memory
// now p is a dangling pointer

p = new int; // reuse for a new address

也可以定义一个 NULL 的空指针:

int *ptr = NULL;

也可以指向一个数组:

int *p = NULL; // Pointer initialized with null
p = new int[20]; // Request memory
delete [] p; // Delete array pointed to by p

注意释放内存时要加上方括号[]

动态内存分配很有用,如当程序需要读取一张图片时,你提前并不知道图片的大小,需要多大的内存空间来存储。这时候使用动态内存来定义就很方便了。

数据大小

虽然不同类型数据的内存占用大小和不同架构的设备有关或使用的编译器,但 c++ 有一个最小的数据大小定义:
123.png

可以使用 sizeof 指令来获取特定数据类型当前占用内存空间,如:

sizeof(int)

返回值为此类型数据的内存大小,单位为字节:

cout << "char: " << sizeof(char) << endl;
cout << "int: " << sizeof(int) << endl;
cout << "float: " << sizeof(float) << endl;
cout << "double: " << sizeof(double) << endl;
int var = 50;
cout << "var: " << sizeof(var) << endl;

/* Outputs
char: 1
int: 4
float: 4
double: 8
var: 4
*/ 

也可以获取数组的内存占用大小:

double myArr[10];
cout << sizeof(myArr) << endl; 

//Outputs 80

一个 double 占用 8 个字节,所以此数组共使用 80 个字节。

可以使用 sizeof 分别读取整个数组和单个元素的内存空间来计算数组元素个数:

int numbers[100];
cout << sizeof(numbers) / sizeof(numbers[0]);

// Outputs 100

以上就是 c++ 数据类型及指针的介绍。

标签: none

添加新评论