指针
指针的作用:
指针可以保存一个内存地址,可以通过指针间接控制内存
使用指针时,可以通过 解引用 的方式来找到指针指向的内存
指针前用星号 * 代表解引用,找到指针指向的内存中的数据
(网友说:& 和 * 是起相反作用的 两个符号)
在32位操作系统下,指针占用4个字节空间;64位 --> 8个字节
(VS和Dev编译器都可以自己选择用64位还是32位对代码进行编译)
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
内存编号 0~255 为系统占用内存,不允许用户访问
int * p = NULL;
*p = 100; // 会报错,0~255 不能自己写
野指针:指针变量指向非法的内存空间
总结:空指针和野指针都不是我们自己申请的空间,因为不要访问,会报错。
const修饰指针
const修饰指针有三种情况:
- const修饰指针 – 常量指针
- const修饰常量 – 指针常量
- const既修饰指针,又修饰常量
int a = 10;
int b = 20;
int * p = &a;
const int * p = &a;
常量指针
特点:指针的指向可以修改,但是指针指向的值不可以修改
比如:
*p = 30; // 错误,指针指向的值不可以修改
p = &b; // 正确,指针指向可以修改
int * const p = &a;
指针常量
特点:指针的指向不可以改,指针指向的值可以改
比如:
*p = 30; // 正确,指针指向的值可以修改
p = &b; // 错误,指针指向不可以修改
const int * const p = &a;
特点:指针的指向和指针指向的值都不可以修改
怎么记:看到 * 就是指针,看到 const 就是“常量”(固定死、不可修改的意思)
代码:
#include <iostream>
using namespace std;
// 定义指针
int main()
{
int a = 10;
int * p;
p = &a;
// int * p = &a;
cout<<"a的地址为:"<<&a<<endl;
cout<<"指针 p 为:"<<p<<endl;
// 解引用加星号
*p = 1000;
cout<<"a=:"<<a<<endl;
cout<<"*p=:"<<*p<<endl;
// 指针所占用内存空间
cout<<"sizeof(int*) = "<<sizeof(p)<<endl;
cout<<"sizeof(int*) = "<<sizeof(int*)<<endl;
system("pause");
return 0;
}
运行结果:
a的地址为:0x22fe34
指针 p 为:0x22fe34
a=:1000
*p=:1000
sizeof(int*) = 8
sizeof(int*) = 8
请按任意键继续. . .
指针和数组
作用:利用指针访问数组中的元素
我有一个疑问:
数组的元素,一个占 4个字节
(64位系统)指针占用 8 个字节
当指针 偏移一个单位时,不就是偏移8个字节吗?
为什么 for 循环里可以正常循环10次,正常输出 所有数组元素呢?
在Q群里问了网友,网友说:指针偏移指的是 它指向的对象 做偏移
总结:指针的地址偏移的量和保存这个地址的指针类型有关
有两个网友的帖子可以参考一下
C语言指针偏移技巧
C语言中的指针加减偏移量
代码:
#include <iostream>
using namespace std;
// 指针和数组
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
cout<<sizeof(arr[0])<<endl;
int * p = arr; // 数组名就是数组的首地址
cout<<sizeof(int*)<<endl;
// cout<<"利用指针访问第一个元素"<<*p<<endl;
// p++; // 让指针向后偏移4(32位)/8(64位) 个字节
// cout<<"利用指针访问第二个元素"<<*p<<endl;
cout<<"所有元素:"<<endl;
for(int i = 0;i<10;i++)
{
cout<<*p<<" ";
p++;
}
cout<<endl;
system("pause");
return 0;
}
运行结果:
4
8
所有元素:
1 2 3 4 5 6 7 8 9 10
请按任意键继续. . .
指针和函数
作用:利用指针作函数参数,可以修改实参的值
注意(网友说的):
地址传递同样会开辟内存空间,数据类型就是指针变量
也就是说,除非指针指向了结构体,否则省内存就是无稽之谈
值传递: 修改函数内部,但是不修改main
地址传递: 函数内部会修改,main也修改
代码:
#include <iostream>
using namespace std;
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout<<"值传递函数内部"<<endl;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
}
void swap02(int* p1, int* p2)
{
int temp = * p1;
* p1 = * p2;
* p2 = temp;
cout<<"地址传递函数内部"<<endl;
cout<<"a = "<<* p1<<endl;
cout<<"b = "<<* p2<<endl;
}
int main()
{
int a = 1;
int b = 2;
//值传递:修改函数内部,但是不修改main
swap(a,b);
cout<<"值传递后 main"<<endl;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
//地址传递:函数内部会修改,main也修改
swap02(&a,&b);
cout<<"地址传递后 main"<<endl;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
system("pause");
return 0;
}
运行结果:
值传递函数内部
a = 2
b = 1
值传递后 main
a = 1
b = 2
地址传递函数内部
a = 2
b = 1
地址传递后 main
a = 2
b = 1
请按任意键继续. . .
指针、数组、函数
案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序
#include <iostream>
using namespace std;
// 冒泡排序函数
void bubbleSort(int * arr, int len) // int * arr 也可以写成 int arr[]
{
for(int i=0;i<len-1;i++)
{
for(int j=0;j<len-1-i;j++)
{
if (arr[j]>arr[j+1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
// 打印数组
void printArray(int * arr, int len)
{
for(int i=0;i<len;i++)
{
cout<<arr[i]<<" ";
}cout<<endl;
}
int main()
{
int arr[10]={4,3,6,9,1,2,10,8,7,5};
int len = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr,len);
printArray(arr,len);
system("pause");
return 0;
}
运行结果:
1 2 3 4 5 6 7 8 9 10
请按任意键继续. . .