【指针】指针详解(3)

文章目录

  • 前言
  • 字符指针变量
    • 常量字符串
  • 数组指针
    • 数组指针和指针数组的区分
    • 二维数组传参的本质
  • 函数指针
    • 函数指针数组
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:
在计算机编程的世界里,指针如同魔法钥匙,揭示着内存的奥秘。本博客将带你深入了解指针,它不是枯燥的理论,而是解锁程序设计新境界的引导。无需畏惧,让我们一同探索指针的神奇之处。


提示:以下是本篇文章正文内容,下面案例可供参考

字符指针变量

关于字符指针变量,我们来着重看一个与指针相关的面试题目

#include 
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

【指针】指针详解(3)_第1张图片

在编译器上运行之后不难发现,答案第一个不相等,第二个相等,那么原因是什么?

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同⼀个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。


这里补充一个常量字符串的知识

常量字符串

常量字符串是指在程序中定义后不可修改的字符串。在C语言中,常量字符串通常使用字符数组表示,且在定义时直接赋值。以下是一个简单的例子:

#include 

int main() {
    // 常量字符串的定义和使用
    const char* greeting = "Hello, World!";

    // 尝试修改常量字符串,会导致编译错误
    // greeting[0] = 'h';  // 错误示例,不允许修改常量字符串

    // 打印常量字符串
    printf("%s\n", greeting);

    return 0;
}

在这个例子中,greeting 被定义为常量字符串,任何尝试修改字符串内容的操作都会导致编译错误。这是因为常量字符串是不可变的。

数组指针

数组指针是指向数组的指针。在C语言中,数组指针的定义可以通过以下方式实现:

#include 

int main() {
    // 定义一个整型数组
    int numbers[] = {1, 2, 3, 4, 5};

    // 定义一个指向整型数组的指针
    int (*ptrToArray)[5];  // 指向包含5个整数的数组的指针

    // 将数组的地址赋给数组指针
    ptrToArray = &numbers;

    // 通过数组指针访问数组元素
    for (int i = 0; i < 5; ++i) {
        printf("Element %d: %d\n", i, (*ptrToArray)[i]);
    }

    return 0;
}

在这个例子中,ptrToArray 是一个指向包含5个整数的数组的指针。通过将数组的地址赋给这个指针,我们可以使用它来访问数组中的元素。请注意,数组指针的声明中要包含数组的大小。

数组指针和指针数组的区分

数组指针和指针数组是两个不同的概念。

  1. 数组指针:

    • 数组指针是指向数组的指针,它指向整个数组,而不是数组中的单个元素。
    • 声明格式为 type (*ptrName)[size];,其中 type 是数组元素的类型,size 是数组的大小。

    举例说明:

    int numbers[] = {1, 2, 3, 4, 5};
    int (*ptrToArray)[5];  // 指向包含5个整数的数组的指针
    ptrToArray = &numbers;
    
  2. 指针数组:

    • 指针数组是一个数组,其中的每个元素都是一个指针。
    • 声明格式为 type *ptrArray[size];,其中 type 是指针指向的类型,size 是数组的大小。

    举例说明:

    int num1 = 1, num2 = 2, num3 = 3;
    int *ptr1 = &num1, *ptr2 = &num2, *ptr3 = &num3;
    int *ptrArray[] = {ptr1, ptr2, ptr3};  // 指针数组
    

在第一个例子中,ptrToArray 是一个指向包含5个整数的数组的指针,而在第二个例子中,ptrArray 是一个包含三个指针的数组。这两者的区别在于指针数组的元素是指针,而数组指针指向整个数组。

二维数组传参的本质

理解数组指针的概念对于理解二维数组传参的本质很有帮助。在C语言中,可以使用数组指针来传递二维数组。

考虑以下的例子:

#include 

void printMatrix(int (*matrix)[3], int rows, int cols) {
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int twoDArray[2][3] = {{1, 2, 3}, {4, 5, 6}};

    // 通过数组指针传递二维数组
    printMatrix(twoDArray, 2, 3);

    return 0;
}

在这个例子中,printMatrix 函数接受一个指向包含3个整数的数组的指针,同时传递了数组的行数和列数。这就是二维数组传参的本质:使用数组指针来接收数组的地址,并传递其他必要的信息,如行数和列数(即二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址)。

需要注意的是,行数(rows)通常是必需的,因为数组指针本身并不能提供该信息。这种方式有效地通过指针传递二维数组,充分利用了数组指针的灵活性。

函数指针

可以去看我的这篇博客

函数指针数组

函数指针数组是一个数组,其中的每个元素都是指向函数的指针。定义和使用函数指针数组可以让我们灵活地处理多个不同类型的函数。

以下是一个简单的例子,演示如何定义和使用函数指针数组:

#include 

// 定义两个函数
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    // 定义函数指针数组,包含两个指向函数的指针
    int (*operation[2])(int, int) = {add, subtract};

    // 使用函数指针数组调用不同的函数
    int result1 = operation[0](10, 5);  // 调用 add 函数
    int result2 = operation[1](10, 5);  // 调用 subtract 函数

    // 打印结果
    printf("Addition result: %d\n", result1);
    printf("Subtraction result: %d\n", result2);

    return 0;
}

在这个例子中,operation 是一个包含两个函数指针的数组。每个函数指针都指向一个接受两个整数参数并返回整数的函数。通过使用函数指针数组,我们可以选择调用不同的函数,实现了一种动态切换函数的机制。这在某些情况下可以用于实现类似于策略模式的设计。

总结

在本博客中,我们深入研究了C语言中的指针概念。字符指针用于处理字符串,数组指针允许更灵活地操作数组,而函数指针使我们能够动态选择和调用不同的函数。通过理解这些指针的概念,我们可以更高效地处理内存和实现灵活的程序设计。本文通过简洁而深入的方式,为读者提供了对这些重要概念的清晰认识。

你可能感兴趣的:(c语言,java,开发语言,c语言,c++,后端,数据结构)