程序员指针介绍

无论您是否意识到,使用过的绝大多数程序都以某种方式使用了指针。也许您曾经遇到过 NullPointerException 。作为程序员,即使您自己没有实现指针,编写的代码也很有可能会使用指针。

今天,我将向您展示指针的工作方式,因此您不妨了解一下数组和数组的工作原理。列出了编程入门的工作。本文将比以往更多地基于理论,但是坚持下去,指针非常复杂!

编译代码

在深入研究指针之前,您需要了解如何构建和构建代码。被执行-也许您已经知道这一点。本节将有相当笼统的陈述-适用于多数种语言的内容,但不一定全部适用。

让我们重新开始。每台计算机都使用二进制文件。这就是机器代码

从机器代码开始的下一步是组装。这是某种人类可读的格式。尽管编程仍然很复杂,但还是可以的。汇编由执行任务的一系列简单命令组成,被称为低级编程语言。可以编写复杂的程序,但是表达抽象概念很困难,并且需要很多考虑。

许多视频游戏和高性能应用程序都以汇编语言编写了一些逻辑,因为它们的速度是真实的如果您知道自己在做什么,就会发现增加。但是,对于绝大多数编程项目,您根本不需要任何汇编。

因此,如果机器代码太难编写而汇编太难编程,该怎么办?你写代码用?这是高级语言的用处。高级语言使程序易于编写。您可以使用类似于您的母语的语言进行编程,并且可以轻松表达复杂的算法。您可能听说过许多高级语言(并且肯定会使用用它们编写的程序):

  • BASIC
  • C ++
  • Lisp
  • 这些语言现在非常古老,许多语言是在1950年代初期开发的!几乎每种现代编程语言都是高级语言,包括PHP和Python。每天都有更多的语言被发明(尽管现在可能已经足够了),但是如果计算机需要机器代码,您的代码仍然可以正常工作吗?

    这里是编译的地方。编译器是一个程序将您的高级代码转换为可以执行的形式。这可能是另一种高级语言,但通常是汇编语言。某些语言(例如Python或Java)将您的代码转换为称为 bytecode 的中间阶段。以后需要再次编译,通常是按需完成,例如程序运行时。这被称为及时编译,并且非常流行。

    内存管理

    现在,您知道编程语言是如何工作的,让我们来看一下内存高级语言管理。对于这些示例,我将使用伪代码-伪代码不是用任何特定语言编写的,而是用于显示概念而非确切语法的。今天,这在大多数情况下都类似于C ++,因为这是最好的高级语言(在我看来)。

    对于本节,如果您了解RAM的工作原理,将会很有帮助。

    大多数语言都有变量-存储一些数据的容器。您必须显式定义数据类型。某些动态类型化的语言(例如Python或PHP)可以为您处理此问题,但还是必须这样做。

    假设您有一个变量:

    int myNumber;

    此代码声明了一个名为< strong> myNumber ,并将其数据类型设置为整数。编译后,计算机将此命令解释为:

    “找到一些空内存,并保留足够大的空间来存储整数"

    该命令执行后,内存不能被其他程序使用。它尚不包含任何数据,但已为您的myNumber变量保留。

    现在为变量分配一个值:

    myNumber = 10;

    要完成此任务,您的计算机将访问它的保留值内存位置,然后将存储在其中的任何值更改为这个新值。

    现在,一切都很好,但是如何不保留内存位置呢?如果程序保留了他们喜欢的所有内存,则RAM将立即填满-这将导致非常缓慢的系统。

    为避免此潜在问题,许多语言都采用了垃圾收集器,用于销毁超出范围的变量(并因此释放保留的内存位置)。

    您可能想知道什么范围是,为什么它如此重要。范围定义变量或程序使用的任何内存的限制和寿命。当变量不能再被任何代码访问时(即垃圾收集器进入时),变量就处于“超出范围"。下面是一个示例:

    function maths() {    int firstNumber = 1;}int secondNumber = 2;print(firstNumber + secondNumber); // will not work

    该示例将无法编译。变量 firstNumber 数学函数中,因此属于范围。不能从声明它的函数外部访问它。 这是一个重要的编程概念,理解它对于处理指针至关重要。

    这种处理内存的方式称为堆栈。这是绝大多数程序的工作方式。您无需了解使用它的指示,而且它的结构相当好。堆栈的缺点是速度。由于计算机必须分配内存,跟踪变量并运行垃圾回收,因此开销很小。这对较小的程序来说很好,但是高性能任务或数据密集型应用程序呢?

    输入:指针。

    指针

    让我们看看如何在堆栈上分配变量:

    int numberOne = 1;int numberTwo = numberOne;

    这是简单的语法;变量 numberTwo 包含数字1。它的值是在分配过程中从 numberOne 变量复制过来的。

    如果要获取变量的内存地址,请使用它的值,则必须使用&符号。这称为 of 操作符,是指针工具包的重要组成部分。

    int numberOne = 1;int numberTwo = &numberOne;

    现在 numberTwo 变量 points 到一个内存位置,而不是将数字复制到自己的新内存位置。如果要输出此变量,则它不是数字1(即使它存储在内存位置中)。它会输出它的内存位置(大概是2167,尽管它随系统和可用RAM的不同而不同)。要访问存储在指针中的值而不是存储位置,您必须取消引用。这将直接访问该值,在这种情况下,该值将为第一。以下是取消引用指针的方式:

    int numberTwo = *numberOne;

    取消引用运算符是一个星号(*)。

    这是一个很难理解的概念,所以让我们再次查看它:

  • 运算符(&)的地址存储内存地址。
  • 取消引用运算符(* )访问值。
  • 声明指针时,语法略有变化:

    int * myPointer;

    int 的数据类型在此是指指针指向的数据类型,而不是指针本身的类型。

    现在,您知道什么是指针了,您可以对它们做一些非常巧妙的技巧!使用内存时,操作系统将顺序启动。您可以将RAM视为鸽子洞。有很多孔可以存储东西,一次只能使用一个。区别在于,这些鸽子洞均已编号。分配内存时,操作系统从最低编号开始,然后开始工作。永远不会在随机数之间跳转。

    使用指针时,如果已分配数组,则可以通过简单地增加指针来轻松导航到下一个元素。

    这就是有趣的地方。当您将值传递给函数时(使用存储在堆栈中的变量),这些值将被复制到函数中。如果这些是大变量,则您的程序现在将它们存储两次。函数完成后,您可能需要一种返回这些值的方法。函数通常只能返回一件事-如果要返回两,三或四件事怎么办?

    如果将指针传递给函数,则只会复制内存地址(这很小) )。这样可以节省您的CPU大量的工作!也许您的指针指向了一个巨大的图像数组-您的函数不仅可以处理存储在完全相同的内存位置中的完全相同的数据,而且一旦完成,就无需返回任何内容。整洁!

    不过,您必须非常小心。指针仍然可以超出范围,并由垃圾收集器收集。但是,不会收集存储在内存中的值。这称为内存泄漏。您不能再访问数据(因为指针已被破坏),但它仍在消耗内存。这是许多程序崩溃的常见原因,如果有大量数据,它可能会失败。在大多数情况下,如果泄漏量大(使用的内存超过系统的内存),操作系统将杀死程序,但这是不希望的。

    调试指针可能是一场噩梦,尤其是当您正在处理大量数据,或者循环工作。它们的缺点和难以理解的确值得您在性能上进行权衡。尽管请记住,但不一定总是需要它们。

    今天就这样。希望您对复杂的话题有所了解。当然,我们还没有涵盖所有要了解的内容-这是一个非常复杂的主题。如果您有兴趣了解更多信息,强烈建议您在24小时内使用C ++。

    如果这有点复杂,请查看我们的最简单编程语言指南。

    标签: