#include
#include <stdio.h>
using namespace std;
//指针 内存
int main()
{
//一、声明和初始化指针
int* ptr; //int ptr; int * ptr; 在C++中,int是一种复合类型,是指向int的指针
//ptr是指针(地址),而ptr是int,而不是指针
//初始化指针,在这种情况下,被初始化的是指针,而不是它指向的值。
//也就是说,下面的语句将pt(而不是pt)的值设置为&higgens
int higgens = 5;
int *pt = &higgens;
//指针的危险
/*重要一点:在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向数据的内存。
为数据提供空间是一个独立的步骤
*/
long *fellow;
//*fellow = 2333; //错误:没有分配用来存储数据的指针
//重点:一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址;这是关于使用指针的金科玉律
//demo-------------------------------------------------------
float test = 9.9;
float * ff = &test;
cout << ff << endl;
cout << sizeof(ff) << endl; //4
cout << sizeof(float*) << endl; //4
cout << sizeof(*ff) << endl; //4
double test2 = 9.9;
double * dou = &test2;
cout << sizeof(*dou) << endl; //8 double对应8个字节
//指针
int *ps1 = new int;
int *pq = ps1; //pq指针指向同一块内存块
delete pq;
//一般来说,不要创建两个指向同一内存块的指针
//delete ps; //错误:不能删除同一个内存块两次
//二、使用new来创建动态数组
int* psome = new int[10]; //get a block of 10 ints
//new运算符返回第一个元素的地址
delete[] psome; //释放动态内存
/*使用new和delete时,应该遵守的规则:
1、不要使用delete来释放不是new分配的内存
2、不要使用delete释放同一块内存两次
3、如果使用new[]为数组分配内存,则应使用delete[]来释放
4、如果使用new为一个实体分配内存,则应使用delete(没有方括号)来释放
5、对空指针应该delete是安全的
*/
/*demo 将指针p3看作数组名来使用,p3[0]为第一个元素,依次类推
指针与数组名的区别:p3=p3+1; 不能修改数组名的值,但指针是变量,因此可以修改它的值。
*/
double *p3 = new double[3];
p3[0] = 0.2; //将p3看作数组名
p3[1] = 0.5;
p3[2] = 0.8;
cout << "p3[1]=" << p3[1] << endl; //0.5
p3 = p3 + 1; //指针加1
cout << "Now p3[0]=" << p3[0] << endl; //0.5
cout << "p3[1]=" << p3[1] << endl; //0.8
p3 = p3 - 1; //指针回答最开始的地方
delete [] p3; //释放内存
/*指针、数组和指针算术
C++中,将数组名解释为数组第一个元素的地址;将指针变量加1后,增加的量等于它指向类型的字节数
*/
double wages[3] = {10000.0,20000.0,30000.0};
short stacks[3] = {3,2,1};
//两种方式获得数组的地址
double *pw = wages;
short *ps = &stacks[0];
//数组元素
cout << "pw=" << pw << ", *pw=" << *pw << endl;
pw = pw + 1;
cout << "pw指针加1后" << endl;
cout << "pw=" << pw << ", *pw=" << *pw << endl;
cout << endl;
cout << "ps=" << ps << ", *ps=" << *ps << endl;
ps = ps + 1;
cout << "ps指针加1后:" << endl;
cout << "ps=" << ps << ", *ps=" << *ps << endl;
cout << "使用数组下标获取两个数组元素:" << endl;
cout << "stacks[0]=" << stacks[0] << ", stacks[1]=" << stacks[1] << endl;
cout << "使用指针获取两个数组元素:" << endl;
cout << "*stacks=" << *stacks << ",*(stacks+1)" << *(stacks+1) << endl;
cout << "size of wages array" << sizeof(wages) << endl;
cout << "size of pw pointer" << sizeof(pw) << endl;
/*
运行结果:
pw=00F6FB94, *pw=10000
pw指针加1后 //double为8个字节
pw=00F6FB9C, *pw=20000
ps=00F6FB84, *ps=3
ps指针加1后: //short为2个字节
ps=00F6FB86, *ps=2
使用数组下标获取两个数组元素:
stacks[0]=3, stacks[1]=2
使用指针获取两个数组元素:
*stacks=3,*(stacks+1)2
size of wages array24 //3*8=24
size of pw pointer4 //指针类型占用4个字节
*/
/*指针和字符串
*/
int tmp[2] = { 1, 2 };
cout << tmp << endl; //tmp[0]的地址 但是如果将int改为char tmp就不是输出第一个字符
/*数组名是第一个元素的地址,因此cout语句中的flower是包含字符的char元素的地址
1、如果给cout提供一个字符的地址,则它将从该字符开始打印,直到遇到空字符为止;
2、在cout和多数C++表达式中,char数组名、char指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址
*/
char flower[10] = "rose";
cout << flower << "s are red" << endl; //roses are red
printf("flower=%s\n", flower); //flower=rose
printf("flower=%c\n", flower[0]); //flower=r
/*demo ----------------------------------------------------------------
*/
char animal[20] = "bear";
const char *bird = "wren"; //“wren”实际表示的是字符串的地址
char *pd; //指针没有初始化
cout << animal << "and";
cout << bird << endl;
//cout << pd << endl; //指针没有初始化
cout << "Enter a kinf of animal:";
//在将字符串读入程序时,应使用已分配的内存地址;该地址可以是数组名,也可以是使用new初始化过的指针
cin >> animal; //动物的长度需要小于20
//cin >> pd; //这样写绝对是错误的,因为指针pd没有指向任何分配的内存
pd = animal; //让指针pd指向animal字符串
cout << pd << "!" << endl;
cout << "Before using strcpy()" << endl;
//将animal赋给pd并不会复制字符串,而只是复制地址。这样,这两个指针将指向相同的内存单元和字符串
cout << animal << "at" << (int*)animal << endl; //foxat0037F664
cout << pd << "at" << (int*)pd << endl; //foxat0037F664
pd = new char[strlen(animal)+1 ];
strcpy(pd,animal);
/*strcpy()函数接收2个参数,第一个是目标地址;第二个是要复制的字符串的地址;
需要确定,分配了目标空间,并有足够的空间来存储副本;
strncpy(),函数接收3个参数,第三个参数——要复制的最大的字符数
*/
cout << "After using strcpy()" << endl;
cout << animal << "at" << (int*)animal << endl; //foxat0037F664
cout << pd << "at" << (int*)pd << endl; //foxat0077D060 //new在离animal数组很远的地方找到了所需的内存空间
delete[] pd;
/*
运行结果:
bearandwren
Enter a kinf of animal:fox
fox!
Before using strcpy()
foxat0037F664
foxat0037F664
After using strcpy()
foxat0037F664
foxat0077D060
*/
/*使用new创建动态结构
通过使用new可以创建动态结构。同样,“动态”以为着内存是在运行时,而不是编译时分配的;
将new用于结构分为两步:创建结构与访问其成员
如果结构标识符是结构名,则使用句点标识符;如果标识符是指向结构的指针,则使用箭头运算符;
另外一种访问结构成员的方法是:如果ps是指向结构的指针,则*ps就是被指向的值——结构本身。
由于*ps是一个结构,因此(*ps).price是该结构的price成员。
*/
struct inflatable
{
char name[20];
float volume;
double price;
};
inflatable *pa = new inflatable; //为结构体分配内存
cout << "Enter name of inflatable item";
cin.get(pa->name, 20);
cout << "Enter volume in cubic feet";
cin >> (*pa).volume;
cout << "Enter price";
cin >> pa->price;
cout << endl;
cout << "Name:" << (*pa).name << endl;
cout << "Volume:" << pa->volume << endl;
cout << "Price:" << pa->price << endl;
delete pa;
system("pause");
return 0;
}
#include
#include <stdio.h>
using namespace std;
char * getname(void);
int main()
{
/*new和delete
要避免内存泄露,最好养成一种习惯,即同时使用new和delete运算符,在自由存储空间上动态分配内存,随后便释放它
/
char * name; //定义指针,没有分配内存
name = getname(); //分配内存
cout << name << “at” << (int)name << endl;
delete[] name; //释放内存
name = getname();
cout << name << "at" << (int *)name << endl;
delete[] name;
system("pause");
return 0;
}
/*
1、temp数组 仅当getname()函数活动时存在。当程序控制权回到main()时,temp使用的内存将自动释放
2、函数将输入读入到一个大型的临时数组中,然后使用new[]创建一个刚好能够存储该输入字符串的内存块
*/
char * getname(void)
{
char temp[80]; //暂时内存
cout << “Enter last name:”;
cin >> temp;
char *pn = new char[strlen(temp) + 1]; //实际内存 smaller space
strcpy(pn, temp); //将temp中的字符串复制到新的内存中
return pn; //函数返回pn,这是字符串的副本
}
/*运行结果:
Enter last name:helloworld
helloworldat006469D0
Enter last name:smile
smileat00646998
*/
#include
#include
using namespace std;
int main()
{
char *tmpBufMsg = new char[100];
strcpy_s(tmpBufMsg,6, "hello");
/*
说明:
指针tmpBuf和tmpBufMsg指向同一段内存区域的首地址,可以通过调试看出来
但是为什么打印出来的地址是不同的?
因为程序需要为指针本身分配内存
打印出来的,其实是指针的地址
*/
char *tmpBuf = tmpBufMsg;
//指针本身的地址
cout << &tmpBuf << endl;
cout << &tmpBufMsg << endl;
cout << tmpBuf << endl;
cout << tmpBufMsg << endl;
system("pause");
return 1;
}
/*
00EFFA2C
00EFFA38
hello
hello
*/
/*
//发送报文
MsgFuncCompStart tmpMsg;
tmpMsg.SetTestServerInfo(ipaddr, index,pid);
char *tmpMsgBuf = new char[tmpMsg.GetMsgLength()];
if (NULL == tmpMsgBuf)
{
printf(“allocate block error\n”);
return false;
}
char *tmpBuf = tmpMsgBuf; //tmpBuf与tmpMsgBuf指向同一块内存区域的首地址
tmpMsg.Encode(tmpBuf); //在Encode中对tmpBuf进行了处理,指针tmpBuf指向内存块的位置不断向后移动,移动的距离正好等于tmpMsg.GetMsgLength()的长度
printf(“Encode send Message =%s\n”, tmpBuf);//kong 为空,是因为指向内存块的末尾地址
printf(“Encode send Message =%s\n”, tmpMsgBuf); // no kong 不空,是因为指向内存块的首地址,从首地址开始读取数据
m_SendMessageWriter->SendTopicData(tmpMsgBuf, tmpMsg.GetMsgLength(),1); //所以,这边使用指针tmpMsgBuf
//将内存块区域释放 同一个内存块不能释放两次
if (NULL != tmpMsgBuf)
{
delete[] tmpMsgBuf;
tmpMsgBuf = NULL;
}
*/