- C++
备战CSP-J初赛21天打卡计划。DAY4-DAY4-数据类型、存储单位、指针2
- 2024-9-3 21:47:52 @
指针和引用
近4年初赛考察:
题号 | 题型 | 分值 | |
---|---|---|---|
2022 | 第3题 | 单项选择 | 2分 |
难易度:简单
2024年备考建议
指针是无法在复赛考察的,所以在初赛考察的可能性大,大家平常写题目又不用,所以在初赛备考时应该引起重视。
结合2024新修订的考试大纲。除了指针本身的概念,涉及到指针的知识点共有3个:
1.基于指针的数组元素访问 2.字符指针 3.指向结构体的指针
什么是指针
指针是一种数据类型,专门存放地址。指针变量在64位系统中占八个字节,在32位系统中占四个字节。
一个内存单元的位置叫做内存单元的地址,通常用取地址符 &
表示,scanf
中&a
表示将键盘输入的内容存放到变量a
的地址中。
指针变量的声明
指针变量声明的一般形式为:
type *pointer-name
例如: int *ptr
,声明了一个整型的指针变量ptr
。这意味着当执行ptr++
操作时,指针的地址会自动加4,原来整型指针加1时会指向下一个int
(整数)。
指针变量的初始化
指针变量一旦存在,必须进行初始化,就像main
函数里的整型变量,不赋初值就会是一个随机数一样,指针变量不赋初值就会成为“野指针”, 把整个程序搞崩溃!!!如果没什么特定的位置那么就给指针赋为空, 即prt = NULL
。
通常指针变量的初始化也可以和声明合并,如下:
double num = 3;
double *pNum = #
指针变量的赋值
对于两个指针变量 ptr1
和 ptr2
, 执行ptr2 = ptr1
, 表示ptr1
和ptr2
指向同样的地址,也就是说,两个指针指向同一个内存单元,对ptr2
的任何改动都会影响ptr1
的值,反之亦然。
需要注意的是, cout << *ptr
输出的是指针ptr
指向的内存单元中的数值而非内存单元的地址。
🧩真题解析
阅读程序写结果
#include <iostream>
#include <cstdio>
using namespace std;
void function(char *a, char *b) {
a = b;
(*a)++;
}
int main() {
char c1, c2, *p1, *p2;
c1 = 'A';
c2 = 'a';
p1 = &c1;
p2 = &c2;
function(p1, p2);
cout << c1 << c2 << endl;
return 0;
}
本题定义了两个字符型变量c1
和c2
,初始值分别为'A'
和'a'
,以及两个字符型指针p1
和p2
,分别将c1
和c2
的地址赋值给p1
和p2
,然后调用函数function
,将指针p1
和p2
的值,也就是c1
和c2
的地址传入函数中。在函数中使用赋值语句让指针p1
指向p2
,也就是变量c2
的地址。并将该地址中的数值加一,即将字符'a'
的ASCII码加1,变成字符'b'
。函数返回后,输出变量c1
和c2
的值,其中c1
的值没有发生变化,而c2
的值从'a'
变成了'b'
,所以输出结果是'A'
和'b'
。
字符指针
字符指针通常用于存储字符串。可以定义一个指向字符的指针变量,并将其初始化为指向字符串的第一个字符。然后,可以使用指针访问整个字符串或只访问特定的字符。
举个例子:
#include <iostream>
using namespace std;
int main() {
// 定义字符指针变量并初始化为指向字符串的第一个字符
char *str = "Hello, world!";
// 输出整个字符串
cout << "String: " << str << endl;
// 输出第一个字符
cout << "First character: " << *str << endl;
// 使用指针访问特定字符
cout << "Third character: " << *(str + 2) << endl;
return 0;
}
在上面的示例中,我们定义了一个名为str
的字符指针变量,并将其初始化为指向字符串"Hello, world!"
的第一个字符。可以使用指针变量访问整个字符串,或者只访问特定的字符。注意,*(str+2)
访问的是指针指向的第三个字符,因为str
指向的是字符串的第一个字符。
指向结构体的指针
可以定义一个指向结构体的指针变量,然后使用它来访问结构体中的成员变量。通常将结构体的指针作为函数参数,以便在函数内部修改结构体的值。
以下是定义指向结构体的指针的示例:
#include <iostream>
using namespace std;
// 定义一个结构体
struct Person {
string name;
int age;
};
int main() {
// 定义一个指向Person类型的指针变量
Person *p;
// 动态分配内存
p = new Person;
// 使用指针访问结构体成员变量
p->name = "Alice";
p->age = 20;
// 输出结构体成员变量
cout << "Name: " << p->name << endl;
cout << "Age: " << p->age << endl;
// 释放内存
delete p;
return 0;
}
在上面的示例中,我们定义了一个指向Person
类型的指针变量p
,然后使用new
运算符动态分配了一个Person
类型的内存空间,将其地址赋给p
。然后,可以使用指针p
访问结构体成员变量,并使用delete
运算符释放内存空间。
引用
什么是引用
引用是对被引用对象的一个别名,是一种语法上的简化,因此可以直接访问被引用对象的值。
在 C++ 中,引用是在定义时就将其绑定到一个对象上,并且不可更改其绑定对象,因此,引用与其绑定对象的关系类似于常量指针。
在使用引用时,并不需要使用取地址符 &
来获取被引用对象的地址,而是直接使用引用名即可。这是因为在编译时,编译器会将引用名替换为其绑定对象的地址,因此使用引用时相当于直接使用了被引用对象的地址。
引用和指针的三个不同
(1)不存在空引用,引用必须连接到一块合法的内存;指针可以赋值为NULL。
(2)一旦引用被初始化为一个对象,就不能被指向到另一个对象;指针可以在任何时候指向到另一个对象。
(3)引用必须在创建时被初始化,指针可以在任何时间被初始化。
引用变量的声明
// 声明简单的变量
int i;
double d;
// 声明引用变量
int &r = i;
double &s = d;
函数参数传递的三种方式
函数通常有三种参数传递的方式:
1 传值,就是把调用函数中的变量的值传递给被调用函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在被调用函数里对形参的改变不会影响到函数外的变量的值。
2 传址,就是传变量的地址赋给函数里形式参数的指针,使指针指向真实的变量的地址,因为对指针所指地址的内容的改变能反映到函数外,也就是能改变函数外的变量的值。
3 传引用,传引用使用引用变量作为函数参数。能达到使用的效果如传址,可是使用方式如传值。指针可以使用操作符*
和->
来访问指针所指向的对象,而引用可以直接使用变量名来访问所引用的对象。传指针需要手动管理内存,需要使用new和delete等操作符,而传引用不需要。
综上所述,传引用是一种更加方便、安全、简洁的参数传递方式,但在某些情况下,传指针也是必要的,特别是在需要动态分配内存的情况下。
历年真题
1、运行以下代码片段的行为是( )
- A 将x的值赋为201
- B 将y的值赋为101
- C 将q指向x的地址
- D 将p指向y的地址
1 条评论
-
xinao015 LV 1 @ 2024-9-4 19:41:40
C
- 1