C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(上)

简介: C初阶--指针初阶(下):指针运算+指针和数组+二级指针+指针数组(上)

一.指针运算🌴


1.曾经用过的案例:写一个模拟实现字符串的函数

前提说明:字符串在传参的时候,或者说作为一个表达式的时候,它的值是首字符的地址,它并不是把“abcdef”传给了my_strlen函数,而是把首字符'a'的地址传过去了,首字符'a'的地址是char类型的地址,需要一个char*的指针接收

#include<stdio.h>
int my_strlen(char* str)
{
  int count = 0;
  while (*str != '\0')
  {
    count++;
    //str++;//指针+整数
    str = str + 1;
  }
  return count;
}
int main()
{
  int len = my_strlen("abcdef");
  printf("%d\n", len);
  return 0;
}

fb00147035e1486bb7b7510f2c508e09.png

 思路:看str指向的那个字符是什么,不是‘\0’,计数器count++,指针str是一个char*的指针,+1跳过一个char类型的变量,最后当遇到'\0',返回count作为返回值。


2.指针+-整数🌾

#define N_VALUES 5

float values [ N_VALUES ];

float * vp ;

// 指针 +- 整数;指针的关系运算

for ( vp = & values [ 0 ]; vp < & values [ N_VALUES ];)

{

   * vp ++ = 0 ;

}

b2e59a37d9374ddcac6fe7e210a8d81e.png


3.指针-指针🌏

指针- 指针 == 地址 - 地址

前提:

  1. 两个指针指向同一块空间,指针的类型是一致的
  2. 指针 - 指针得到的是指针和指针之间的元素个数(这是语法规定的)

由前面我们可知指针+-整数是等于指针的,那如果指针 - 指针不就是整数了吗,分两种情况


方法1:大地址-小地址或者小地址-大地址⛅

1.大地址-小地址:随着数组下标的增长,地址是由低到高变化

int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int n = &arr[9] - &arr[0];
  printf("%d\n", n);
  return 0;
}

执行:

76c845c5cce34a91b354293bf47324a6.png

  • 为什么是9?答:语法规定。(但是还是不明白为什么是9)⛄

个人思路:把内存监视调出来:可以观察一下它们的地址

7e10e50d8e044c0d8056a5d5ca06192d.png

🍄实践证明:

用它们的地址相减:减出一个24,这个24是一个16进制数,可以代表它们之间相差的内存空间, 将16进制24转换为10进制后,是36byte也就是相差9个(整型)元素的地址空间


2.小地址 - 大地址(特殊情况)

int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  int n = &arr[0] - &arr[9];
  printf("%d\n", n);
  return 0;
}

6ed2ffbb48564bc2a04d549e178b5848.png

方法2:模拟实现指针相减🌱

int my_strlen(char* str)
{   
  char* start = str;
  while (*str!='\0')
  {
    str++;
  }
  return str - start;
}
int main()
{
  int len = my_strlen("abcdef");
  printf("%d\n", len);
  return 0;
}


执行:

b4b60c9e52b34e8cbafa5f0bf9c5bb32.png

图解:

951aae7c134c48068934f387c1442b02.png


4.指针的关系运算

for(vp = &values[N_VALUES]; vp > &values[0];)

{

   *--vp = 0;

}

经过修改之后的代码

for ( vp = & values [ N_VALUES - 1 ]; vp >= & values [ 0 ]; vp -- )

{

   * vp = 0 ;

}

关于这两种写法的理解:

441ee2f0dc2f4a75b807a8ec082d2d53.png

关于野指针的知识:vp1:起始位置这不是越界了吗?没有。

🌵理解:

这个位置后面的空间虽然不属于values数组,但指向这个位置是没有形成越界访问的这种效果,仅仅指向是没有问题的!!!只有当对vp1解引用了或者说访问数组values[5]的元素了,通过vp1改数组values后面空间的数据了,那确实是非法访问了🌳

关于vp1和vp2指针问题:

实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

🌐 标准规定:

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

指向第一个元素之前的那个内存位置的指针进行比较。

相关文章
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
206 3
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
414 4
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
206 2
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
206 1