C/C++ 指针和数组

指针和数组基本等价的原因在于指针算术和C/C++内部处理数组的方式。

#include <iostream>
using namespace std;

int main()
{
    double wages[3] = {100.0, 200.0, 300.0};
    short stacks[3] = {3, 2, 1};

    double *pw = wages;
    short *ps = &stacks[0];

    cout << "pw = " << pw << ", *pw = " << *pw <<endl;
    pw = pw + 1;
    cout << "add 1 to the pw pointer:\n";
    cout << "pw = " << pw << ", *pw = " << *pw << "\n\n";

    cout << "ps = " << ps << ", *ps = " << *ps <<endl;
    ps = ps + 1;
    cout << "add 1 to the ps pointer\n";
    cout << "ps = " << ps << ", *ps = " << *ps <<"\n\n";

    cout << "access two elements with array notation\n";
    cout << "stacks[0] = " << stacks[0] << ", stacks[1] = " << stacks[1] <<endl;

    cout << "access two elements with pointer notation\n";
    cout << "*stacks = " << *stacks << ", *(stacks + 1) = " << *(stacks + 1) <<endl;

    cout << sizeof(wages) << " = size of wages array\n";
    cout << sizeof(pw) << " = size of pw pointer\n";


    return 0;
}

(1) 上面程序能运行的原因是C/C++将数组名解释为地址和所有的数组一样,wages存在下面的等式:wages = &wages[0] = 数组中第一个元素的地址;。

(2) 将指针变量加1后,其增加的值等于指向的类型占用的字节数。pw指向double类型,因此对pw加1就会让它的值增加8个字节。

(3) 从程序的输出可知,*(stacks + 1)和stacks[1]是等价的。同样,*(stacks + 2)和stacks[2]是等价的。

在很多情况下,可以以相同的方式使用指针名和数组名。区别之一是,可以修改指针的值,而数组名是常量

pointername = pointername + 1;     //合法
arrayname = arrayname + 1;         //不合法

(4)另一个区别是,对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度,即使指针指向一个数组。

(5)数组名被解释为其第一个元素的地址,而对数组名应用地址运算符时,得到的是整个数组的地址:

short tell[10];
cout << tell << endl;    //是第一个元素的地址
cout << &tell << endl;   //是整个数组的地址

从数字上看,两个地址相同,但从概念上说,&tell[0]是一个2字节内存块的地址,而&tell是一个20字节内存块的地址。因此,表达式tell+1将地址值加2,而表达式&tell+2将地址加20。换句话说,tell是一个short指针(*short),而&tell是一个这样的指针,即指向包含20个元素的short数组(short(*)[20])。

(6)使用指针的金科玉律:一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址。

 

 

使用new创建动态结构

使用new创建动态结构的步骤:创建结构和访问成员。创建动态结构时,不能将成员运算符句点用于结构名,因为这种结构没有名称,只是知道它的地址。C/C++专门为这种情况提供了一个运算符:箭头成员运算符(->)。

另一种访问结构成员的方法是,如果ps是指向结构的指针,则*ps就是被指向的值——结构本身。由于*ps是一个结构,因此(*ps).price是该结构体的price成员。C++的运算符优先规则要求使用括号。

#include <iostream>
using namespace std;

struct asd
{
    char name[20];
    float volume;
    double price;
};

int main()
{
    asd *ps = new asd;
    cout << "Enter asd item: ";
    cin.get(ps->name, 20);
    cout << "Enter volume:";
    cin >> (*ps).volume;
    cout << "Enter price:";
    cin >> ps->price;
    cout <<endl;
    cout << "Name: " << (*ps).name <<endl;
    cout << "Volume: " << ps->volume << " cubic feet\n";
    cout << "Price: " << ps->price <<endl;
    delete ps;
    return 0;
}

 

使用new和delete的实例

#include <iostream>
#include <cstring>
using namespace std;

char *getname(void);

int main()
{
    char *name;

    name = getname();
    cout << name << " at " << (int *)name <<endl;
    delete []name;    //指针所指向的空间被释放,但指针还可以使用

    name = getname();
    cout << name << " at " << (int *)name <<endl;
    delete []name;

    return 0;
}

char *getname()
{
    char temp[80];
    cout << "Enter last name: ";
    cin >> temp;
    char *pn = new char[strlen(temp) + 1];
    strcpy(pn, temp);

    return pn;
}

获取空间后,getname()使用标准库函数strcpy()将temp中的字符串复制到新的内存快中,该函数并不检查内存块是否容纳字符串,但getname()通过使用new请求合理的字节数来完成这样的工作。

 

二级指针实例

A是指向指针的指针,称为二级指针用于存放二级指针的变量称为二级指针变量

#include <iostream>
using namespace std;

struct asd
{
    int year;
};

int main()
{
    asd s1,s2,s3;
    s1.year = 2017;
    asd *pa = &s2;
    pa->year = 2018;
    asd trio[3];
    trio[0].year = 2019;
    cout << trio->year <<endl;
    const asd *arp[3] = {&s1, &s2, &s3};
    cout << arp[1]->year <<endl;
    const asd **ppa = arp;
    cout << (*ppa)->year <<endl;
    cout << (*(ppa+1))->year <<endl;
    return 0;
}

由于ppa指向arp的第一个元素,因此*ppa为第一个元素(ppa是一个指向结构指针的指针,因此*ppa是一个结构指针),即&s1。所以,(*ppa)->year为s1的year成员(*ppa等价于arp[0],所以(*ppa)->year等价于arp[0]->year)。之前提到的,如果ps是指向结构的指针,则*ps就是被指向的值——结构本身。所以还可以这样访问arp[0]所指向的s1:

cout << (**ppa).year <<endl;

 

使用数组区间

对于处理数组的函数,必须将数组中的数据种类、数组的起始位置和数组中元素数量提交给它;传统的C/C++方法是,将指向数组起始处的指针作为一个参数,将数组长度作为第二个参数。另一种给函数提供信息的方法是指定元素区间,这可以通过传递两个指针来完成,一个指针标识数组开头,另一个指针标识数组的尾部。STL使用"超尾"概念来指定区间。也就是说,对于数组而言,标识数组结尾的参数将是指向最后一个元素后面的指针。

#include <iostream>
using namespace std;

const int Asize = 8;
int sum_arr(const int *begin, const int *end);

int main()
{
	int asd[Asize] = {1, 2, 4, 8, 16, 32, 64, 128};
	int sum = sum_arr(asd, asd + Asize);
	cout << "Total asd: " << sum <<endl;
	sum = sum_arr(asd, asd + 3);
	cout << "First three elements: " << sum <<endl;
	sum = sum_arr(asd + 4, asd + 8);
	cout << "Last four elements: " << sum <<endl;
	return 0;
}

int sum_arr(const int *begin, const int *end)
{
    const int *pt;
    int total = 0;

    for(pt = begin; pt != end; pt++)
    {
        total = total + *pt;
    }
    return total;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tyler_Zx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值