C/C++的指针

1、 指针的概念:

指针是一个变量,它存储的是另一个变量的内存地址,而不是变量的值。
指针变量的声明:在C/C++等语言中,我们通过使用星号*来声明一个指针变量。例如,int *ptr; 这行代码声明了一个名为ptr的指针变量,它指向一个整数类型的内存地址。
指针变量的赋值:我们需要将一个变量的地址赋值给指针变量。这可以通过使用取地址运算符&来实现。例如,int x = 10; ptr = &x; 这段代码将变量x的地址赋值给了指针变量ptr。
接下来,我们详细讲解指针变量的定义和使用:

2、指针变量的定义和使用

定义指针变量

在C/C++中,我们可以这样定义一个指针变量:

// 定义一个指向整数的指针变量  
int *ptr;  
  
// 定义一个指向字符的指针变量(通常用于字符串)  
char *str;  
  
// 定义一个指向浮点数的指针变量  
float *fptr;

使用指针变量

使用指针变量主要包括以下几个步骤:

初始化指针:在将指针用于访问或修改数据之前,必须确保它指向了一个有效的内存地址。这可以通过将某个变量的地址赋值给指针来实现。

int x = 10;  
int *ptr = &x;  // ptr现在指向变量x的内存地址

通过指针访问数据:一旦指针指向了一个有效的内存地址,我们就可以通过解引用指针(使用星号*)来访问或修改该地址中的数据。

// 通过指针访问x的值  
printf("Value of x: %d\n", *ptr);  // 输出: Value of x: 10  
  
// 通过指针修改x的值  
*ptr = 20;  
printf("Value of x after modification: %d\n", x);  // 输出: Value of x after modification: 20

指针的运算:指针可以进行一些基本的算术运算,如加法、减法,但这些运算的结果是基于指针所指向的数据类型的大小来计算的。

// 假设int类型占4个字节  
int arr[5] = {1, 2, 3, 4, 5};  
int *p = arr;  // p指向arr的第一个元素  
  
// p + 1将指向arr的第二个元素  
printf("Value at p + 1: %d\n", *(p + 1));  // 输出: Value at p + 1: 2

空指针和野指针:空指针(NULL)是一个特殊的指针值,它不指向任何有效的内存地址。野指针是指已经被释放或从未被初始化的指针,它们指向的内存地址是不确定的,使用它们可能导致程序崩溃或数据损坏。因此,在使用指针之前,一定要确保它指向了一个有效的内存地址。
动态内存分配:除了使用已经存在的变量地址外,我们还可以使用如malloc、calloc、realloc等函数来动态地分配内存,并将返回的地址赋值给指针。这种方式可以让我们在运行时根据需要分配或释放内存。

3、void*万能指针

void* 是一种通用指针类型,它允许你存储任何数据类型的地址,但是你不能直接通过 void* 类型的指针来访问或修改它所指向的数据,因为编译器不知道这个地址处的数据是什么类型。

当你需要将 void* 指针转换为其他类型的指针以进行解引用或操作时,你需要进行显式的类型转换(也称为强制类型转换)。在 C/C++ 中,这通常使用类型转换运算符(如 (int*)、(char*) 等)来完成。

下面是一个简单的例子,展示如何使用 void* 指针并在需要时将其转换为其他类型的指针:

#include <stdio.h>  
#include <stdlib.h>  
  
void print_int(void* ptr) {  
    // 将 void* 转换为 int*  
    int* int_ptr = (int*)ptr;  
    // 现在可以安全地解引用 int_ptr  
    printf("The value is: %d\n", *int_ptr);  
}  
  
int main() {  
    int x = 42;  
    // 将 int 变量的地址传递给 void* 类型的函数  
    print_int(&x);  
    return 0;  
}

在这个例子中,print_int 函数接受一个 void* 类型的参数,并在函数内部将其转换为 int* 类型的指针,然后解引用该指针以打印整数的值。

注意,虽然 void* 提供了灵活性,但使用它时也需要谨慎,因为它可能隐藏类型错误,导致程序在运行时出现错误。在使用 void* 时,最好确保你明确知道指针所指向的数据类型,并在使用前进行正确的类型转换。

4、常量指针和指针常量的概念

*const (号)左边放,是指针变量指向常量 - 常量指针

指的是当const关键字出现在指针声明中的星号*左边时,该指针是一个指向常量的指针,即你不能通过这个指针去修改它所指向的数据,但你可以改变这个指针指向的地址。例如:

const int *p; // p 是一个指向 int 类型常量的指针

在这个例子中,p 是一个指针,它可以指向一个 int 类型的变量,但是你不能通过 p 来修改那个变量的值(因为它是常量的)。但是,你可以让 p 指向另一个地址。

*const (号)右边放,是指针常量指向变量 - 指针常量

指的是当const关键字出现在指针声明中的星号*右边时,该指针是一个指针常量,即你不能改变这个指针指向的地址,但你可以通过这个指针去修改它所指向的数据。例如:

int *const q; // q 是一个指向 int 类型变量的指针常量

在这个例子中,q 是一个指针常量,你不能改变 q 指向的地址,但是你可以通过 q 来修改它所指向的 int 类型的变量的值。

*const (号)两边放,是指针常量指向常量 - 常量指针常量

指的是当const关键字在指针声明中既出现在星号左边又出现在星号右边时,该指针是一个指向常量的指针常量,即你不能改变这个指针指向的地址,也不能通过这个指针去修改它所指向的数据。例如:

const int *const r; // r 是一个指向 int 类型常量的指针常量

在这个例子中,r 是一个指针常量,你不能改变 r 指向的地址。同时,r 指向的是一个常量,所以你也不能通过 r 来修改它所指向的 int 类型的变量的值。

总结

05-02 05:06