指针和结构体
指针
定义与使用:
-
作用:通过指针访问内存(指针就是地址)
- 内存编号从0开始记录,一般使用十六进制表示
- 指针变量存放的就是内存地址
-
使用:
int a = 10; int * p = &a; // 定义 cout << *p << endl; // 10
-
注意点:指针定义的
*
类似数据类型定义,标明这是一个指针;使用的时候*
是解引用,代表取出内存中的值。这是两个不同的概念
指针占用内存空间:在32位系统(x86)中,指针占用4个字节(存放16进制地址);在64位(x64)系统中,占用8个字节。
cout << sizeof(int *) << end; // 4
cout << sizeof(double *) << endl; // 4
空指针:指针变量指向内存地址为0的地址空间
- 用途:初始化指针,并且空指针指向地址空间不可以进行访问(内存地址0~255为系统使用)
野指针:指针变量指向非法地址空间
int * p = (int *)0x1100; // 没有申请的地址空间不能随意使用
cout << *p << endl; // 程序崩溃
const和指针:
-
const修饰指针:常量指针
int a = 10; int b = 10; const int * p = &a; // 指针指向的值不可以改,指针指向可以修改 *p = 20; // error p = &b; // right
-
const修饰变量:指针常量
int * const p = &a; // 指针纸箱不可以改,指针指向的值可以改 p = &b; // wrong
-
const修饰指针和变量:
const int * const p = &a;
-
记忆技巧:看const修饰的是什么,const修饰什么 什么就不能改。如
const int *
那么*
操作就不能改 也就是* p
不能改。
**指针和数组:**使用指针访问数组中的数据
int arr[10] = {1,2,3,4,5,6,7,8,9,9}
int * p = arr; // arr就是数组首地址
cout << *p << endl; // 1
p++;
cout << *p << endl; // 2
**指针和函数:**指针作为函数参数,可以修改实参的值。
// 经典交换案例
void swap(int *p1, int *p2) {
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
int a = 10, b = 20;
swap(&a, &b)
结构体
结构体概念:结构体属于用户自定义数据类型,允许用户存储不同的数据类型
定义和使用:
struct 变量名(类型名称) {};
struct Student {
string name;
int age;
double grade;
};
struct Student s1; // 创建方式1
s1.name = "john"; s1.age = 18; s1.grade = 100.0;
struct Student s2 = {"James", 19, 80.0}; // 创建方式2
struct Student { // 创建方式3
...
} s3;
s3.name = "jacika";
// 创建时,struct 关键字可以省略
Student s4;
结构体数组:将自定义数据类型放在数组中,方便维护
struct 类型名称 数组名称 [];
stuct Student stuArr [2] = {
{"John",18, 100.0},
{"Iving", 19, 90.0}
}
cout << stuArr[0].name << endl; // John
**结构体指针:**通过指针访问结构体成员
->
符号
struct studen * p = s1; //struct关键字可以省略
cout << p->name << endl; //
结构体嵌套:结构体中成员也是一个结构体
struct teacher {
int id;
string name;
int age;
struct student stu; // student结构体需要在teacher结构体之前定义
}
teacher t1;
t1.id = 1001;
t1.name "monica";
t1.age = 40;
t1.stu.name = "Janmes";
t1.stu.age = 19;
t1.stu.grade = 90.0;
结构体作为函数参数:将结构体作为参数向函数中传递
//struct Student s1; // 创建方式1
// s1.name = "john"; s1.age = 18; s1.grade = 100.0;
//struct Student s2 = {"James", 19, 80.0};
void print_str1(struct Student stu) { // 值传递
cout << str.name <<endl;
str.name = "111";
}
void print_stu(struct Student * str) { // 地址传递
cout << str->name << endl;
str -> name = "222"
}
int main() {
print_str1(s1);
print_stu(&s2);
cout << s1.name << endl; // john
cout << s2.name << endl; // 222,地址传递改变了结构体内容
}
结构体中使用const:
void print_stu_new(const Student *s) { // 假设实参的数据量很大,值传递将会非常浪费内存空间。而使用地址传递,可以减少内存空间,而且不会复制新的副本。
s->age = 150; // 报错,const不能修改
cout << s->age << endl;
}
int main() {
Student ss = {"James", 19, 80.0};
print_stu_new(&ss);
}