c语言进阶部分详解(指针初阶)

简介: c语言进阶部分详解(指针初阶)

0c01b338705b4d449af3474aa8df563d.png大家好!,前段时间一直在准备数学建模竞赛,现在也是忙完了。抓紧继续给大家带来c语言的内容。今天给大家带来指针初阶部分的讲解


当我们谈论C语言中的指针时,实际上是在讨论一种非常重要的概念,因为指针是C语言的核心之一。它们允许我们直接访问内存中的数据,这在编写高效和灵活的程序时非常有用。让我们来深入了解一下指针的概念和用法



 

一.指针是什么

1.指针的初步理解

 指针理解的2个要点:

1. 指针是内存中一个最小单元的编号,也就是地址

2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:指针就是地址,口语中说的指针通常指的是指针变量


内存示意图:


指针变量:

我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量

#include<stdio.h>
int main()
{
  int a = 7;//创建变量时,在内存里开辟的一篇空间
  int* pa = &a;//这里我们对变量a,取出它的地址,可以使用&操作符
  //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
  //中,p就是一个之指针变量
  return 0;
}

总结:指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)


2.指针的大小

在C语言中,指针的大小是根据计算机体系结构和操作系统的不同而变化的。通常情况下,指针的大小与计算机的位数相关。在32位系统中,指针的大小通常是4字节(32位),而在64位系统中,指针的大小通常是8字节(64位)


3.总结

  • 指针是用来存放地址的,地址是唯一标示一块地址空间的。
  • 指针的大小在32位平台是4个字节,在64位平台是8个字节



二.指针和指针类型

变量有不同的类型,整形,浮点型等。那指针有没有类型呢?

指针确实有:

char  *pc = NULL;
int   *pi = NULL;
short *ps = NULL;
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;


这里可以看到,指针的定义方式是: type + * 。

其实:

char* 类型的指针是为了存放 char 类型变量的地址。

short* 类型的指针是为了存放 short 类型变量的地址。

int* 类型的指针是为了存放 int 类型变量的地址 

接下来探求指针类型的意义


三.指针类型的意义

指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)

比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节

1.指针+-整数

int main()
{
  int n = 10;
  char* pc = (char*)&n;
  int* pi = &n;
  printf("%p\n", &n);
  printf("%p\n", pc);
  printf("%p\n", pc + 1);
  printf("%p\n", pi);
  printf("%p\n", pi + 1);
  return 0;
}


a812fbba4ec94ba2af677e0a5207b632.png

2.解引用


可以看到pc与pi的数值均是相等的,当运行完*pc=0后,只是改变了第一个字节的数值。


当运行完*p=0后,只是改变四个字节的数值



四.野指针

概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

1.野指针成因

①指针未初始化

int main()
{
  int* pa;
  *pa = 10;
  return 0;
}


连编译器都会阻止我们使用未初始化的指针


指针越界访问

int main()
{
  int arr[10] = { 0 };
  int* p = arr;
  for (int i = 0; i <= 11; i++)
  {
    *(p++) = i;
  }
  return 0;
}


当指针指向的范围超出数组arr的范围时,p就是野指针: 自然也会报错


749fd413ecef4ec687b1b26cb32a7f1a.png

指针指向的空间释放

int* createInt() {
    int num = 5;
    int* ptr = &num;
    return ptr;
}
int main() {
    int* ptr = createInt();
    printf("%d\n", *ptr);  // 输出5,但是这是不安全的操作
    // 在这之后,ptr成为了野指针,因为它指向的内存空间已经被释放
    printf("%d\n", *ptr);  // 未定义的行为,可能输出垃圾值或导致程序崩溃
    return 0;
}


在上面的示例中,函数createInt()创建了一个整型变量num,并将其地址赋给指针ptr,然后返回了该指针。在main()函数中,我们打印了指针ptr所指向的值,输出结果为5。但是在createInt()函数结束后,变量num的生命周期结束,其所占用的内存空间被释放。此时,指针ptr仍然保留着之前的内存地址,成为了野指针。在后续的打印操作中,我们试图访问野指针ptr所指向的值,这是不安全的操作,可能导致程序出现未定义的行为  


 

五.指针运算

1.指针+-整数

  • 指针加减整数是指对指针进行加减运算,其中整数表示要加减的偏移量。这种操作通常用于在指针上移动一定的距离,以便访问指针指向的内存位置
  • 指针的加减运算是基于指针所指向的数据类型的大小进行的。例如,如果一个指针指向一个int类型的变量,那么对该指针进行加1的操作,将使指针指向下一个int类型的变量。同样地,对指针进行减1的操作,将使指针指向前一个int类型的变量
#include<stdio.h>
int main()
{
  int arr[] = { 1,2,3,4,5 };
  int* pa = arr;
  for (int i = 0; i < 5; i++)
  {
    printf("%d ", *(pa++));
  }
  return 0;
}

2.指针-指针

指针-指针操作是指对两个指针进行减法运算,得到它们之间的偏移量。这种操作通常用于计算两个指针之间的距离或元素的个数

接下来我们可以利用这一点来模拟实现strlen()函数

int my_strlen(char* pa)
{
  char* start = pa;
  while (*pa)
  {
    pa++;
  }
  return pa - start;
}
int main()
{
  char arr[] = "hello";
  printf("%d", my_strlen(arr));
  return 0;
}


3.指针的关系运算

  • ==:判断两个指针是否相等。如果两个指针指向同一个内存地址,则它们相等,返回1;否则返回0
  • !=:判断两个指针是否不相等。如果两个指针指向不同的内存地址,则它们不相等,返回1;否则返回0
  • >:判断一个指针是否大于另一个指针。指针的大小是根据指针所指向的内存地址来比较的。如果第一个指针指向的地址在第二个指针指向的地址之后,则第一个指针大于第二个指针,返回1;否则返回0
  • <:判断一个指针是否小于另一个指针。指针的大小是根据指针所指向的内存地址来比较的。如果第一个指针指向的地址在第二个指针指向的地址之前,则第一个指针小于第二个指针,返回1;否则返回0
  • >=:判断一个指针是否大于等于另一个指针。如果第一个指针大于第二个指针或两个指针相等,则返回1;否则返回0
  • <=:判断一个指针是否小于等于另一个指针。如果第一个指针小于第二个指针或两个指针相等,则返回1;否则返回0

4.注意

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较


六.指针和数组

1.指针是一个变量,用于存储内存地址。指针变量可以指向任何类型的数据,包括数组。通过指针,我们可以间接地访问和操作内存中的数据。

2.数组就是数组,可以存放一组数,数组的大小是取决于元素的类型和个数。

3.数组的数组名是数组首元素的地址,地址是可以放在指针变量中的。通过指针可以访问一个数组的元素  

  • 数组名和指针:在C语言中,数组名可以被看作是一个指向数组首元素的指针。例如,对于数组int arr[5]arr可以被视为指向arr[0]的指针。因此,可以通过指针来访问数组中的元素,例如*arr表示数组的第一个元素,*(arr + 1)表示数组的第二个元素。
  • 此外,指针算术运算也可以应用于数组名。例如,arr + 1表示数组的第二个元素的地址,arr + 2表示数组的第三个元素的地址。这是因为数组的元素在内存中是连续存储的
int main()
{
  int arr[] = { 1,2 };
  int* pa = arr;
  printf("%p\n", arr);
  printf("%p\n", &arr[0]);
  return 0;
}

3386429c6ed14bcc8f4adeb258cbe923.png


 

七.二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

这就是 二级指针

int main()
{
  int a = 10;
  int* pa = &a;//一级指针
  int** ppa = &pa;//二级指针
  printf("%d\n", a);
  **ppa = 0;//通过两次解引用来改变值
  printf("%d\n", a);
  return 0;
}

782f3797cda24220be26359bf397ba98.png


八.指针数组

指针数组是是数组,是存放指针的数组

可以使用指针数组,模拟一个二维数组

int main()
{
  int arr1[] = { 1,2,4,6 };
  int arr2[] = { 7,2,4,4 };
  int arr3[] = { 1,2,9,6 };
  int* p[] = { arr1,arr2,arr3 };
  for (int i = 0; i < 3; i++)
  {
    for (int j = 0; j < 4; j++)
    {
      printf("%d ", p[i][j]);
    }
    printf("\n");
  }
  return 0;
}

0c01b338705b4d449af3474aa8df563d.png


指针是C语言中一个强大而复杂的概念。通过使用指针,我们可以直接访问和修改内存中的数据,实现灵活和高效的内存操作。然而,在使用指针时需要小心,避免出现空指针和野指针的问题。希望这篇文章对你理解C语言中的指针部分有所帮助。

目录
相关文章
|
2月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
62 0
|
25天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
79 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
25天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
49 9
|
25天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
42 7
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
126 13
|
29天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
29天前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
103 3
|
1月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
1月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
58 11
|
29天前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
39 1