常见的指针类型和操作c++

在C++中,指针是非常重要的概念,它允许直接操作内存地址。以下是常见的指针类型及其操作:

1. 普通指针

普通指针是最基本的指针类型,用于存储某个变量的内存地址。通过指针,可以间接地访问和修改该变量的值。

 
  

int num = 10;

int* ptr = # // ptr是指向num的指针

*ptr = 20; // 修改num的值为20

常见操作

  • *ptr:解引用指针,访问指针指向的变量。
  • ptr = &var:获取变量的地址,并将其赋给指针。

2. 空指针(nullptr)

空指针是指向“无效”内存地址的指针。在C++中,可以使用nullptr来表示空指针,防止误操作。

 
  

int* ptr = nullptr; // ptr是空指针,未指向任何有效地址

if (ptr != nullptr)

{

// 安全地使用指针

}

常见操作

  • ptr == nullptr:检查指针是否为空指针。

3. 常量指针

常量指针分为两种情况:

  • 指向常量的指针:const int* ptr; 指针指向的内容不能通过该指针修改。
  • 指针常量:int* const ptr; 指针本身是常量,不能指向其他地址。
 
  

const int* ptr = # // 指向常量的指针

//*ptr = 20; // 错误,不能通过ptr修改num i

nt* const ptr2 = # // 指针常量

//ptr2 = &num2; // 错误,ptr2不能指向其他地址

4. 指向指针的指针(多级指针)

指针也可以指向另一个指针,从而形成多级指针。二级指针(指向指针的指针)用于间接访问某个变量的指针。

 
  

int num = 10;

int* ptr = #

int** ptr2 = &ptr; // ptr2是指向ptr的指针

**ptr2 = 20; // 通过ptr2修改num的值为20

5. 函数指针

函数指针用于存储函数的地址,可以用来动态调用不同的函数。

 
  

int add(int a, int b)

{ return a + b; } i

nt (*funcPtr)(int, int) = &add; // 定义函数指针并初始化

int result = funcPtr(2, 3); // 通过函数指针调用add函数

6. 数组指针

数组指针是指向数组的指针,用于操作数组中的元素。

 
  

int arr[5] = {1, 2, 3, 4, 5};

int* ptr = arr; // 数组名本身就是指针,指向数组的首元素

for (int i = 0; i < 5; i++)

{

std::cout << *(ptr + i) << " "; // 访问数组元素

}

7. 智能指针

智能指针是C++11引入的一种指针类型,用于自动管理动态内存,防止内存泄漏。常见的智能指针包括std::unique_ptrstd::shared_ptrstd::weak_ptr

 
  

#include

std::unique_ptr ptr(new int(10)); // 自动管理内存,离开作用域时释放内存

智能指针常见操作

  • std::make_unique():创建unique_ptr
  • std::make_shared():创建shared_ptr

常见指针操作

  • 指针的算术运算:如ptr++ptr--可以移动指针,访问数组或连续内存中的其他元素。
  • 比较指针:可以使用==!=<>等操作符来比较两个指针是否指向相同或不同的地址。

总结

指针是C++中一个强大且灵活的工具,但也容易出错,因此在使用时必须非常小心,确保每个指针都被正确初始化和使用,避免悬空指针、野指针等常见问题。

这里面要注意一个最特殊的指针类型,void* ,它很多场景必不可少,但是又问题多多。

在C++中,void*是一种特殊的指针类型,称为“通用指针”或“未定类型指针”。它具有以下特性和操作:

1. 指向任意类型

void*指针可以指向任意类型的对象,而不需要指定具体的类型。这使得void*在某些场景下非常灵活,比如在实现通用数据结构或处理未知类型的数据时。

 
  

int intVar = 10;

double doubleVar = 20.5;

void* ptr; ptr = &intVar; // ptr可以指向int类型的变量

ptr = &doubleVar; // ptr也可以指向double类型的变量

2. 不能直接解引用

void*指针是类型不确定的,因此不能直接解引用它以访问指向的值。要解引用void*指针,必须首先将其转换为特定的类型指针。

 
  

int intVar = 10;

void* ptr = &intVar;

int* intPtr = static_cast(ptr); // 将void*转换为int*类型

std::cout << *intPtr << std::endl; // 现在可以解引用访问intVar的值

3. 指针算术操作不适用

由于void*指针没有确定的类型,编译器无法确定指针步长,因此不允许对void*指针执行指针算术操作(如ptr++ptr--)。

 
  

void* ptr = nullptr;

// ptr++; // 错误,void*不支持指针算术操作

4. 类型安全问题

由于void*不包含类型信息,使用它时需要小心。将void*转换为错误的类型可能导致未定义行为或崩溃。这使得void*使用起来非常灵活但也容易出错。

 
  

int intVar = 10;

void* ptr = &intVar; // 如果错误地将其转换为double*,可能会导致未定义行为 double* doublePtr = static_cast(ptr);

std::cout << *doublePtr << std::endl; // 未定义行为,可能崩溃

5. 常见使用场景

  • 动态内存分配:如malloc函数返回的就是void*类型,需要转换为特定类型的指针。
  • 通用数据结构:如在实现通用的链表或队列时,void*可以用来存储不同类型的数据。
  • 函数指针:某些函数可以接受void*作为参数,允许传递任意类型的数据。
 
  

void* malloc(size_t size); // malloc返回void*

int* intPtr = static_cast(malloc(sizeof(int) * 10)); // 转换为int*类型

6. void 与 nullptr*

void*可以与nullptr(或C中的NULL)比较,表示指针为空(即不指向任何对象)。

 
  

void* ptr = nullptr;

if (ptr == nullptr)

{ std::cout << "ptr is null" << std::endl; }

总结

void*指针是C++中功能强大的工具,用于处理类型不确定或通用的数据。然而,由于它的类型不安全性,在使用时需要特别小心,确保在解引用之前正确转换类型。void*指针在某些低级编程和系统编程中广泛使用。


char* pStr=0;
short* pSnum=0;
int* pInt=0;
void* pvoid=0;
void** ppvoid=0;


pStr++; //移动一个字节
pSnum++;//移动2个字节
pInt++;//移动4个字节
pvoid++;//这个操作不允许,因为未知大小
ppvoid++;//移动四个字节

//通过这样的方式可以输出查看他们的便宜量:
printf("%d",pStr);

//另外:
struct test
{
    char c;
    short s;
    int i;
    void* pv;
};
//c在结构体里面占4字节,s也占4字节,i也一样,不要问为什么。

//如果有人问你不创建结构体的实例,如何查看他们的内存偏移
struct test* ptest=0;

int ipos = &(ptest->i); //可以这样做,虽然其实不建议,毕竟操作空指针本身就很危险

你可能感兴趣的:(IT生涯,c++,java,开发语言)