数组、指针、字符串

一:数组

 数组是具有一定关系若干对象的集合体,组成数组的对象称为该数组的元素。

1.数组的声明

  • (1)确定数组的名称。
  • (2)确定数组元素的类型。
  • (3)确定数组的结构(包括数组的组维数,每一维的大小)。

一般形式:

        数组类型 标识符[常量表达式1][常量表达式2]……;

注意:数组的元素都是从0开始的,假设一个数组的元素由n个,则最大下标为n-1。

int a[3][4];

2.数组的使用

int a[3] = {1, 2, 3};
for (int i = 0; i < 3; i++)
{
    cout << a[i] << ends;
}
  • 使用数组时,只能分别对数组各个元素进行操作,不能整个对数组进行赋值。
  • 数组访问不能越界,否则会出现越界错误。
  • 数组下标表达式必须是合法的表达式,其结果必须是整数。

3.数组的储存和初始化

(1)数组的储存:

   数组元素在内存中是顺序、连续储存的。

  • 一位数组可以看作是数学上的一个列向量。
  • 二维数组可以看作是数学上的一个矩阵。

(2)数组的初始化

   数组的初始化就是在声明数组时给部分或全部元素赋初值。

//一维数组的初始化
int a1[3] = {1, 2, 3}; //最基本的赋值
int a2[5] = {1, 2, 3}; //给部分元素赋值,对于静态生存期的数组,剩下的元素系统默认为0;动态生存期的数组,每个元素的初值不确定
int a3[] = {1, 2, 3, 4, 5, 6}; //可以不用说明数组的大小

//二维数组的初始化
int b1[2][2] = {1, 2, 3, 4}; 
int b2[2][3] = {{1,2,3}, {4,5,6}};
int b3[][3] = {1, 2, 3}; //第一维的下标个数可以省略不写
const float b4[5] = {1, 2, 3, 4, 5}; //对于声明为常量的数组,必须给定初值

4.数组作为函数参数

#include<iostream>
using namespace std;
void fun1(int a[]) {}//使用数组名传递数据,传递的时地址,一般不指定数组第一维的大小,如果指定,也会被编译器忽略

void fun2(int *a) {}

int main()
{
    int a[3] = {1,2,3};
    fun1(a); //数组名表示数组的首地址,将a的首地址传给fun1函数
    fun1&a[0]); 
    fun1(&a[1]); //此时数组的大小发生变化,传进去的数组时从a数组的第二个元素开始的数组
    //fun2函数同理
}

5.对象数组

#include<iostream>
using namespace std;
//学生类
class Student
{
int stuID;
public:
    Student(int i = 0):stuID(i) {}
    Student() {}
}
int main()
{
    //主函数中创建对象数组 创建形式:对象名 数组名[N],数组中储存的是对象
    Student stu1[3] = {Student(1), Student(2), Student(3)}; //第一种初始化方式,相当于对象的拷贝
    Student stu2[3] = {{1}, {2}, {3}}; //第二种初始化方式,直接分别给出初值
}

二:指针

1.指针变量的声明

指针变量是用于存放内存单元地址的。

int *p;
char *c;

2. & 和 *

  • 在C++中&既表示引用,又表示对一个变量进行取址操作,注意区分使用场合。
  •  * 称为指针操作符,也称解析符,表示获取指针所指向对象的值。

3.指针的赋值

int a[3] = {1, 2, 3};
int *pa = a; //数组名代表数组的首地址,是一个不能被赋值的指针,即指针常量

int b = 3, *p;
p = &b; //&表示取址符,p指向b
  • 可以声明指向常量的指针,此时不能修改指针所指向常量的值,但指针本身可以改变,可以指向别的对象。
int a;
const int *p = &a;
int b;
*p = b; //编译器报错,因为常量指针所指向的值不可以改变
p = &b; //正确,常量指针可指向别的对象
  • 可以声明指针类型的常量,此时指针本身的值不可以改变。
int *const p = &a;
p = &b; //编译器会报错,指针常量的值不可以改变
  • void指针可以储存任何类型的指针。经过使用类型显示转换,void指针可以访问任何类型的数据。

4.指针的运算

指针是一种数据类型,和其他数据类型一样,可以参与部分运算,包括算数运算、关系运算和赋值运算。

  •  设有指针p1和整数n1,p1+n1表示指针p1所指位置后方第n1个数的地址,p1-n1表示指针p1所指位置前方第n1个数的地址。
  • *(p1+n1) 表示p1当前位置后方第n1个数的内容,也可以写作p1[n1],*(p1-n1)表示p1当前位置前方第n1个数的内容,也可以写作p1[-n1]。
  • 指针的逻辑运算指的是相同类型的指针进行的关系运算,不同类型的指针或指针与非0整数之间的运算是毫无意义的。
  • 指针可以和零进行逻辑运算,0专门用于表示空指针,即不指向任何有效地址的指针。空指针也可用NULL表示,在编译器的头文件中有定义NULL的宏,即#define NULL 0

5.用指针处理数组元素

数组为一段连续的空间,恰好契合了指针的特点,因此可以用指针来方便的处理数组。

  •  用指针处理一维数组
int a[6] = {1, 2, 3, 4, 5, 6};
int *pa = a;
for (int i = 0; i < 3; i++)
{
    cout << a[i] << ends; //直接用数组名来访问数组
}

for (int i = 0; i < 3; i++)
{
    cout << *(pa+i) << ends; //*(pa+i)表示数组下标为i的元素
}

for (int i = 0; i < 3; i++)
{
    cout << pa[i] << ends; //pa[i]与*(pa+i)等价
}
  • 用指针处理二维数组
int b[2][3] = {{1,2,3}, {4,5,6}};
int *pb = b; //二维数组名表示二维数组一维下标为0所在行的地址
int i = 1, j = 2;

//b数组的数组名表示b[0],即指向二维数组第一行的地址,地址与第一行第一个元素相同,但是类型不同,类型为int (*p)[3],这里可以理解为从行的角度看待数列

//*b表示b[0]首元素的地址,即b[0][0]的首地址,相当于转化成了一位数组,这里可以理解为具体的从列的角度看待数列

cout << *(*(pb + i) + j) << ends; //等价于b[i][j]
cout << *(pb[i] + j) << ends; //等价于b[i][j]

6.用指针作为函数参数

当需要在不同的函数之间传输大量数据时,程序执行时调用函数的开销就会很大。这时如果需要传递的数据是一段连续的内存区域,就可以只传递数据的起始地址,而不必传数据的所有值,这样就会减少开销,提高效率。

用指针作为函数参数有三个作用:

  • 使实参参与形参指针指向共同的内存空间。
  • 减少函数调用时数据传递的开销。
  • 通过指向函数的指针传递函数代码的首地址。

6.指针型函数

若一个函数的返回值为指针类型,则这个函数就是指针型函数。

int* func(int a[], int length)
{
    ……
    return a; //这时返回数组的首地址,而不是某个变量或者对象,相当于传递了大量数据
}

7.指向函数的指针

未完待续……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值