Discuz! BBS

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1126|回复: 1

指针 Pointer

[复制链接]

254

主题

363

帖子

2431

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2431
发表于 2023-9-27 18:38:25 | 显示全部楼层 |阅读模式
什么是指针
程序中的每个变量和字面量都有一个内存地址。程序使用的函数也同样有其内存地址。这些地址取决于运行程序时,将程序加载到内存的什么地方。而
指针是一个可用于存储内存地址的变量。
但是如果指针只存储内存地址,是不行的,为了使用存储于内存地址上的实体,除了知道该实体在哪里,还需要知道该实体是什么。实体存储在内存中是占用一定字节数的,要使用指针所存储的地址上的数据项,就需要知道数据项的类型。
如此,指针不止存储了地址,还同时表示了数据项的类型。
声明指针
声明指针类似于声明一般变量,但变量类型后面跟一个星号:
  1. long* pLongNumber;      //指向一个长整型的指针。
复制代码
这里,指针存储(将来要赋值的)实体的地址,同时它接受的实体类型是长整型;也就是说,这个指针是“指向long”的指针。
编译器还接受另一种类似的声明方式:
  1. long *pLongNumber, longNumber;      //第一个变量是(指向长整型的)指针,第二个是长整型的一个整数变量
复制代码
注意在C++中,通常约定指针的变量名以p开头,从而使源代码更清晰规泽并容易理解。
初始化指针
指针使用之前一定要初始化。原因是未初始化的指针,如果保存一个垃圾值,之后取值和存值的时候,都能产生程序出错等等危害。下面简要说明一下如何初始化指针:
1、初始化为已定义的变量的地址:
  1. int number = 0;                      //初始化变量
  2. int* pNumber = &number;       //用变量初始化指针的时候,必须先初始化变量本身。
复制代码
2、初始化为空(不指向任何实体):
  1. int* pIntNumber = 0;      //不指向任何实体的指针
复制代码
这种方式叫做初始化为空指针。但是这种初始化方式,如果在给这个指针赋值前就试图获取它的地址(和上面的值,叫解引用),程序就会失败。
有一个办法可以避免这种失败,在程序中定义一个相同数据类型的值,然后初始化指针的时候就指向该值,比如 string GlobalInitialString = "I WILL NEVER FAIL (Global initial String)."
那么一个好习惯就是在解引用任何指针之前,先测试它是否是空指针:
  1. if (pIntNumber == 0)
  2.     cout << endl << "pIntNumber is null. " << endl;
  3. else
  4.     cout << endl << "The dereference value is: " << *pIntNumber << endl;
复制代码
注意上面代码中的解引用,即*pIntNumber还没有正式说明,将在后面具体详细说明,这里先了解是获取指针对应的被赋与指针的实体就可以了。
测试非空还有其他几种书写样式,一般选一种心仪的即可:
  1. if (!pIntNumber)
  2.     cout << endl << "pIntNumber is null. " << endl;
  3. else
  4.     cout << endl << "The dereference value is: " << *pIntNumber << endl;
  5. //Or:
  6. if (pIntNumber != 0)
  7.     cout << endl << "The dereference value is: " << *pIntNumber << endl;
复制代码
在C语言中也可用NULL代表0,(标准库),但C++编译器不一定都是用NULL,所以为了通用起见都用0来表示空。
使用指针
对于已经初始化并已经赋值的指针,就可以加以应用,包括获取指针指向的内存地址,或者指向的实体的实际值。
1、取址运算:
取址运算符&是一个一元运算符,它可以获取实体的内存地址。一般给指针赋值的时候用到它。
  1. long longNumber = 12345L;
  2. long* pLongNumber;
  3. pLongNumber = &longNumber;      //取址运算符,获取变量的保存地址,赋给指针。
复制代码
2、提领运算符:
提领运算指获取指针指向位置的所在位置的实际值。也就是取值运算。
  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. int main(){
  5.     long number = 123L;
  6.     long* pnumber = &number;
  7.     cout << endl
  8.          << "The number stored in address pnumber is :"
  9.          << *pnumber               //提领
  10.          << endl
  11.          << endl;
  12.     return 0;
  13. }
复制代码
注意在指针相关运算中,“*”号既可以作提领运算符,也可以用作声明指针,这就是指针让人混乱的秘密了。
3、指针与数组(包含数组与字符串的知识)指针和数组之间有很密切的联系。数组名其实就是指针(保存了一个地址),在输出语句中,可以将数组名像指针那样操作。
如果输出语句只使用数组名,而该数组不是char类型的数组,则直接输出该数组在内存中的十六进制地址(就是说和直接输出指针相同)。
数组名也可以直接用来初始化指针:
double d_values[10];
double* p_d_values = d_values;
但是也要注意,指针和数组名只是类似性,其实是不一样的,这主要因为指针的内容可以修改,而数组名所表示的地址是固定的。

4、函数指针
5、字符数组(字符串)
char类型的数组有两个含义,1)表示字符数组  2)表示字符串。 其中的区别是字符串的最后一个元素(也可能不仅仅是最后一个元素)要为空字符'\0'。
如果字符数组的最后一个元素不是空字符,则该char仅仅是字符数组而非字符串。
char vowls[5] = {"a", "e", "i", "o", "u"};
仅仅是包含5个元素的字符数组
char vowls2[6] = {"a", "e", "i", "o", "u", "\0"};
则是字符串。
要初始化字符串还有两种方法:
char volws2[] = "aeiou";
char volws2[10] = "aeiou";     注意这种方法将在第6~第10个位置写入空字符'\0'。


使用指针,可以在不规定数组大小的情况下,创建非空字符串字面量
注意用指针初始字符串一定加上const修饰符(若不加const修饰符,则后期可以更改该内容,则更改后的内容如果没以空字符结尾——'\0',取值的时候就会突破指针界限,一直取值直到遇到第一个空字符为止。所以必须添加const)
const char*   psomechar = "A lucky star.";
cout << psomechar << endl;
注意cout将指向char的指针看作非空字符串,然后输出该字符串。

对于char字符串数组,可以建立指针数组,然后引用数组下标访问每一个元素:
  1. int main()
  2. {
  3.     const char* pnames[] = { "Arnold Schwarzenegger", "Paul Newman", "David Dean"};
  4.     for( int i = 0; i < 3; ++i)
  5.     {
  6.         cout << pnames[i] << endl;
  7.     }
  8.     return 0;
  9. }
复制代码

注意以上每个指针数组的元素也是指针,因为每个元素指向不同的字符串,每个字符串没有冗余,所以使用指针数组占用的内存较少。另外排序和转存都只挪动指针,也可以节省时间和空间。
  1. //获取指针数组的大小:
  2. const int namesSize = sizeof pnames / sizeof pnames[0];
  3. //这里的原理还是用到每一个指针数组的元素都是一个——相同大小的——指针
复制代码

6、为什么使用指针
可以在函数中访问函数外部定义的大块数据
可以动态的为新变量分配内存空间。即在程序执行过程中分配。












回复

使用道具 举报

254

主题

363

帖子

2431

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2431
 楼主| 发表于 2024-2-5 22:37:28 | 显示全部楼层
可以使用指针对字符串排序,具体方法贴在这里:
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|DiscuzX

GMT+8, 2025-4-16 04:18 , Processed in 0.015182 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表