C++ 指针知识点摘录

指针是 C 语言中的一个重要概念,也是 C 语言的一个重要特色。在 C 语言中,指针被广泛使用,它和数组、字符串、函数间数据的传递等有着密不可分的联系。可以说,没有掌握指针就没有掌握 C 语言的精华。
指针可以对内存中各种类型的数据进行快速、直接的处理,也可以为函数间的数据传递提供简洁、便利的方法。正确熟练地使用指针有利于编写高效的程序,但指针使用不当也容易导致严重错误。指针很灵活,也很危险。

定义指针变量

指针变量(简称指针)就是存放地址的变量。其声明形式与一般变量声明相比只是在变量名前多一个星号*,接下来看两个例子。
例1:

int *p;

该例中声明了变量 p 为指向整型值的指针(即变量 p 中可以存放某个整型变量的地址)。这里的*在声明语句中,是指针说明符,表示声明的变量是指针变量。
例2:

float *xPtr, *yPtr, f;

该例子中声明了两个指向浮点型值的指针 xPtr 和 yPtr 以及一个浮点型变量 f 。

指针的性质

① 指针可以赋值为 NULL 或某个地址。具有值 NULL 的指针不指向任何地址;
② 指针是具有特定属性的地址。光有地址只是知道数据存储在内存的某个位置,但怎么访问该位置的数据(即访问多少位,以什么方式访问)还需要指针类型来明确;
例如:使用 int 类型的指针访问其所指向的数据时,会一次性读取32位( int 类型的数据是32位),并使用整型数据的格式访问该数据。所以指针不仅仅是一个地址,还必须有特定的属性(类型)。
③ 数组名可以看成是一个特殊的地址,首先数组名是地址(数组的首地址),其次数组名有属性(数组元素的类型),所以可以把数组名赋值给同类型的指针变量。
例如:

char s[10] = "China";//字符类型的数组表示字符串
char *sptr = s;

第二条语句赋值后 sptr 拥有和 s 同样的值,即数组的首地址,也就是存储字符‘C’的单元的地址。
④ 要访问指针所指向的单元可以使用间接引用运算符*(不同于前面声明语句中的*,这里的*在表达式中,是运算符),*也被称为复引用运算符,它返回其操作数(指针)所指向的对象;
例如:

char s[10] = "China";
char *sptr = s;
cout << *sptr;

将输出指针 sptr 所指的单元中存储的字符(因为 sptr 是 char 类型的指针),也就是输出字符‘C’。(数组的第一个元素)
⑤ 可以通过指针的复引用修改指针所指向的单元;
例如:

char s[10] = "China";
char *sptr = s;
*sptr = 'c';

上述代码会将该存储单元中大写字符的‘C’修改为小写字符的‘c’。
请注意前面代码的输出语句和下面的代码语句的区别:

char s[10] = "China";
char *sptr = s;
cout << sptr;

这条语句将输出字符串“China”。之前学习字符数组时应该知道,语句cout << s;会输出数组 s 中存储的整个字符串,实际上 C++ 在使用 cout 输出 char 类型指针时,不是输出字符指针的值(地址),而是输出从该地址开始的字符串(逐个输出一个个字符,直到碰到 ‘\0’ 为止)。所以cout << sptr;和cout << s;的作用一样,都是输出字符串“China”。
⑥ 访问一个字符串一般也是使用该字符串的首字符的地址;
⑦ 指针也可以参与算术运算。指针加上或减去一个整数 n,其运算结果是指向指针当前指向变量的后方或前方的第 n 个变量。
例如:之前 sptr 指向字符‘C’的存储单元,执行语句sptr++;后 sptr 则指向字符‘h’的存储单元。如下语句:

while(*sptr != ‘\0)
    sptr++;
//则可以使指针 sptr 指向该字符串后面的 '\0'。如果要输出字符串中的部分内容,也可以通过修改指针实现,如:
char s[10] = “China”;
char *sptr = s;
sptr++;
cout << sptr;
//上述代码执行语句`sptr++;`后,指针 sptr 指向了字符 'h' 的存储单元,此时`cout << sptr;`输出的是 sptr 指向的字符串,即“hina”。
//同类型的两个指针可以参与各种关系运算,其结果可以反映两指针所指向的地址之间的位置前后关系。
//例如:
int a[10];
int *p = a, *q = &a[1];
if(p > q)
    cout << “p>q” << endl;
else
    cout << “p<=q” << endl;

上述代码中指针 p 中存放的是 a 的值,也就是 a[0] 的地址,q 中存放的是 a[1] 的地址,而数组元素是按序连续存储的,所以 q 的值要比 p 的值大,程序输出p<=q。

用指针传递参数

C 和 C++ 函数调用的参数传递方式有两种:传值和传引用。
传值只是值的传递,被调用函数则无法修改实在参数的值;
传引用则是实参和形参共享实在参数的存储单元,所以被调用函数可以通过修改形参来修改实参的值。
如果采用传值的方式传递指针值,可以实现类似于传引用的效果。
例如:

#include <iostream>
using namespace std;
// 函数inc:将p指向的整数值加
// 参数:p-int类型指针,指向要加的整数
void inc(int * p)
{
    
    
    (*p)++;     // *p 访问 p 指向的单元,++ 将该单元的数据加
    // 注意不能是 *p++, 因为 * 和 ++ 优先级相同,且右结合,这种写法修改的是 p 的值,而不是 *p 的值
}
int main()
{
    
    
    int a = 10;
    inc(&a);     // 调用 inc 函数,修改 a 的值(传递的是 a 的地址)
    cout << a << endl;     // 输出 a 的值
    return 0;
}

上述程序的输出为11,其中被调用函数 inc 只修改了 main 函数中的局部变量 a 的值,但并没有修改实参的值(实参是&a,即 a 的地址依然没变)。

你理解了吗?猜猜下面的程序会输出什么,做对了说明你理解得差不多了:
#include<iostream>
using namespace std;
int main(){
    
    
	int a=0;
	int *b=&a;
	cout<<&a<<' '<<*b<<' '<<b<<' '<<a<<' '<<&*b<<' '<<*&a<<' '<<&*b<<' '<<*&*b<<' '<<&*&a<<endl;
	return 0;
}
(答案请看文末~

字符串操作函数

C 和 C++ 提供了一系列操作字符串的函数,要使用这些函数只要在代码的头文件部分包含 string.h 即可。
常用的字符串处理函数见下表:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

strstr 函数

在一个长串中查找子串可以使用strstr函数,该函数的函数原型为:

char* strstr(const char* s1, const char* s2);

该函数从 s1 所指字符串中第一个字符起,顺序向后查找出与 s2 所指字符串相同的子串,若查找成功则返回该子串首次出现的首地址,否则返回 NULL。
例如:

char *a="abcdeabcde";
char *b="bcd";
cout<<strstr(a,b)<<endl;

该程序输出结果为“bcdeabcde”,因为strstr(a, b)的返回值为“bcd”在“abcdeabcde”中第一次出现的首地址,所以用 cout 输出时,从该位置的字符开始,逐个输出直到 ‘\0’,即字符串“bcdeabcde”。
当然,查找子串时,也可以从长串的某个位置开始。
例如:

char *a="abcdeabcde";
char *b="bcd";
cout<<strstr(a+4,b)<<endl;

该程序的输出为“bcde”。因为a+4得到一个新地址,即 a 指向的字符串中第一个字符‘e’的地址,从该位置开始查找 b 指向的字符串‘bcd’,得到从字符‘e’开始的第一个“bcd”出现的地址,然后用 cout 输出该地址开始的字符串,即“bcde”。

strlen 函数

另外,下次从什么地方开始查找子串?应该是上次找到子串的开始位置加上子串的长度。其中,函数strlen可以计算字符串的长度,其函数原型为:

int strlen(const char *s);

函数 strlen 只有一个参数 s,它是一个字符指针,代表了一个字符串,函数计算 s 指向字符串的长度并返回。
例如:

char *a="x";
char *b="Hello world!";
cout<<strlen(a)<<endl;  // 输出 1
cout<<strlen(b)<<endl;  // 输出 12

sizeof( ) 函数

输出所占的字节数:

#include<iostream>
#include<cstring>
using namespace std;
int main(){
    
    
	char a[10];
	cout<<sizeof(a)<<' ';
	cout<<sizeof(int)<<' ';
	cout<<sizeof(int*)<<' ';
	cout<<sizeof(char)<<' ';
	cout<<sizeof(char*)<<' ';
	cout<<sizeof(double)<<' ';
	cout<<sizeof(double*)<<' ';
	cout<<sizeof(float)<<' ';
	cout<<sizeof(float*)<<' ';
	return 0;
}

输出:

10 4 8 1 8 8 8 4 8
  • 还可以用 sizeof( ) 计算一个同类型元素数组的元素个数:
#include<iostream>
#include<cstring>
using namespace std;
int main(){
    
    
	char a[]={
    
    1,2,3,4,5,6,7,45,6232};
	cout<<sizeof(a)/sizeof(a[0]);
	return 0;
}
输出:9

上面测试答案如下:
0x6ffdf4 0 0x6ffdf4 0 0x6ffdf4 0 0x6ffdf4 0 0x6ffdf4

猜你喜欢

转载自blog.csdn.net/interestingddd/article/details/114311893
今日推荐