为什么要使用指针? [关闭]

2023-12-11

我知道这是一个非常基本的问题,但在使用高级语言编写了一些项目后,我刚刚开始一些基本的 C++ 编程。

基本上我有三个问题:

  1. 为什么要使用指针而不是普通变量?
  2. 我应该何时何地使用指针?
  3. 如何将指针与数组一起使用?

  • 为什么要使用指针而不是普通变量?

简短的回答是:不要。 ;-) 指针用于不能使用其他任何东西的地方。这要么是因为缺乏适当的功能、缺少数据类型,要么是纯粹为了性能。更多下文...

  • 我应该何时何地使用指针?

简短的回答是:你不能使用其他任何东西的地方。在 C 中,您不支持复杂的数据类型,例如字符串。也无法将变量“通过引用”传递给函数。这就是你必须使用指针的地方。您还可以让它们指向几乎任何东西,链表、结构成员等等。但我们这里不讨论这个。

  • 如何将指针与数组一起使用?

花费很少的努力和很多混乱。 ;-) 如果我们谈论简单的数据类型,例如 int 和 char,数组和指针之间几乎没有什么区别。 这些声明非常相似(但不相同 - 例如,sizeof将返回不同的值):

char* a = "Hello";
char a[] = "Hello";

您可以像这样访问数组中的任何元素

printf("Second char is: %c", a[1]);

索引 1,因为数组从元素 0 开始。:-)

或者你也可以这样做

printf("Second char is: %c", *(a+1));

需要指针运算符(*),因为我们告诉 printf 我们要打印一个字符。如果没有 *,将打印内存地址本身的字符表示形式。现在我们使用角色本身。如果我们使用 %s 而不是 %c,我们会要求 printf 打印 'a' 加一所指向的内存地址的内容(在上面的示例中),并且我们不必将 *在前:

printf("Second char is: %s", (a+1)); /* WRONG */

但这不会只打印第二个字符,而是打印下一个内存地址中的所有字符,直到找到空字符(\0)。这就是事情开始变得危险的地方。如果您不小心尝试使用 %s 格式化程序打印整数类型的变量而不是字符指针怎么办?

char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);

这将打印在内存地址 120 上找到的任何内容,并继续打印直到找到空字符。执行此 printf 语句是错误且非法的,但它可能会起作用,因为在许多环境中指针实际上是 int 类型。想象一下,如果您改用 sprintf() 并将这种太长的“char 数组”分配给另一个变量,而该变量仅分配了一定的有限空间,则可能会导致问题。您很可能最终会覆盖内存中的其他内容并导致您的程序崩溃(如果您幸运的话)。

哦,如果在声明时没有为 char 数组/指针分配字符串值,则必须在为其赋值之前为其分配足够的内存。使用 malloc、calloc 或类似的。这是因为您只声明了数组中的一个元素/一个要指向的内存地址。这里有几个例子:

char* x;
/* Allocate 6 bytes of memory for me and point x to the first of them. */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* Delete the allocation (reservation) of the memory. */
/* The char pointer x is still pointing to this address in memory though! */
free(x);
/* Same as malloc but here the allocated space is filled with null characters!*/
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* And delete the allocation again... */
free(x);
/* We can set the size at declaration time as well */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);

请注意,在对分配的内存执行 free() 后,您仍然可以使用变量 x,但您不知道其中有什么。另请注意,两个 printf() 可能会给出不同的地址,因为不能保证第二次内存分配与第一次分配在同一空间中执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么要使用指针? [关闭] 的相关文章

随机推荐

  • 没有可编译的体系结构(ARCHS=、VALID_ARCHS=armv7 armv7s)

    我使用的是 Xcode 4 5 2 并且有一个无法为运行 iOS 6 0 1 的 iPhone 编译的项目 尽管其他项目使用相同的设置可以正常编译 如下图所示 关于如何解决这个问题有什么想法吗 您可能正在使用一些尚不支持armv7s架构的第
  • 如何从 JavaScript 函数调用 PHP 类方法 [重复]

    这个问题在这里已经有答案了 可能的重复 从 javascript 调用 php 函数 我知道php是服务器端 JavaScript是客户端 但我想知道如何在调用 JavaScript 函数时运行 PHP 方法 下面是我的代码 我知道错误是
  • 将事件/命令与 XamlReader 结合使用

    我正在使用 XamlReader Parse string 动态构建我的数据模板 我遇到的问题是我无法在使用 XamlReader 创建的任何控件上放置任何事件 在网上做了一些研究后 我了解到这是 XamlReader 的一个已知限制 我对
  • 仅当页面位于 React Router Dom 的站点内时,如何返回一页?

    我想创建一个 返回 按钮 如果该页面位于网站内 则该按钮仅返回一页 我试过以下这个答案添加返回按钮 import useNavigate from react router dom function YourApp const naviga
  • pcap_lookupnet 返回错误的 IP 地址

    以下 libpcap 文档中的示例代码生成以下代码 该代码应报告给定接口的 IP 地址 本例中为 eth0 为简洁起见 省略错误检查 include
  • 填充 Azure AD B2C Orchestration 中的电子邮件地址文本框

    我正在使用自定义策略来执行一些用户旅程并使用MFA 的社交和本地帐户 在其中一个步骤中 我询问用户他们的电子邮件地址 我正在使用 LocalAccountDiscoveryUsingEmailAddress 在第一个屏幕上获取他们的电子邮件
  • 在 MVC3 中使用 JQuery 渲染部分视图

    我有一些记录 单击每条记录后 信息需要显示在手风琴中 该信息应该从数据库动态获取 到目前为止我所做的是 创建局部视图 那应该显示详细信息 单击记录后 我调用 jquery 方法并在控制器上执行我的方法 控制器以 Json 形式返回对象 或任
  • 向 Selenium2(WebDriver) chrome 驱动程序添加扩展

    我使用下面的代码使用 webdriver selenium 2 启动 chrome Map
  • Modelica 仿真和方程初始化总时间计算

    我想测量 DAE 系统的总模拟和初始化时间 我对挂钟时间感兴趣 就像 Matlab 中函数 tic toc 给出的时间 我注意到在 Modelica 中 模拟时间有不同的标志 但实际上 与我按下模拟按钮到模拟结束所经过的时间 大约用手机时钟
  • 如何在 Java applet 中显示位图图像?

    我很难弄清楚如何在 Java 小程序中显示图像 或 ImageIcon 以下是我的代码 图片 test bmp 确实存在并且位于 D 驱动器上 但是当我运行它时 我得到的小程序窗口中没有任何内容 有人可以告诉我我缺少什么来使 ImageIc
  • 如何避免最后打印nil?

    我已经编写了这个函数来打印板的状态 但最终 由于没有返回 该函数打印为零 功能 defun show board board dotimes number 8 dotimes number2 8 let pos aref board num
  • 如何在php中提取2个标签之间的文本

    我需要在一堆文本中找到 2 个标签 并保留它们之间的任何文本 例如 如果 开始 标签是 start 结束 标签是 end 鉴于此文本 rtyfbytgyuibg start isnv4b987b6vdc5y6ughnjmn9b8v76cty
  • 如何将动画图像插入仅适用于 Outlook 2013 的电子邮件正文? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我正在尝试将 gif 插入电子邮件正文中 并将其显示在 Outlook 中 我尝试过插入 图片 但它会将 gif 转换为静态图像形式 即使原始图像是动画的 如何在 Outlook 中
  • 如何在这段 PHP 和 MySQL 代码中演示 SQL 注入?

    首先我想指出 这是对我自己的数据库的一次教育尝试 目的是更好地理解 MySQL 注入以保护我自己的代码 我需要找出几个示例来说明如何根据以下代码构建 MySQL 注入 这是一个基本的用户登录系统 我接受用户名和密码而不进行任何转义 user
  • 有没有用 Java 实现的验证 HTML 解析器?

    我需要用 Java 解析 HTML 4 理想情况下 我想要一个与 SAX 兼容的实现 我知道 Java 有许多 HTML 解析器 但是 它们似乎都执行 整理 换句话说 它们将纠正格式错误的 HTML 我不想要这个 我的要求是 没有整理 如果
  • Flutter 键盘使文本字段隐藏

    我是新来的扑腾 我添加了一个带有文本字段的表单 当我单击文本字段并且键盘出现时 文本字段会上升 这是我的代码 Widget build BuildContext context MediaQueryData mediaQuery Media
  • 我想沿着特定路径制作对象的动画

    我必须移动路径上的小矩形 在画布内单击后 矩形会移动 我无法为其设置动画 因为对象只是跳转到所需的点 请在以下位置找到代码Fiddle HTML
  • InstallShield Basic MSI 卸载不显示带有“完成”按钮的对话框

    我使用 InstallShield 2018 并创建了一个 Basic MSI 项目 卸载产品时 它会确认我是否要继续卸载 确认后开始卸载 但随后它就消失了 最后没有显示一个对话框 您可以在其中单击 完成 按钮 因此 用户不知道卸载是否完成
  • 注册全局热键而不禁用其密钥

    我想制作一个程序 即使它在任何时候都不活动 也可以捕获键盘事件 Hooks 太复杂了 我需要做很多事情才能使其正常工作 制作 DLL 读取它等等 所以我决定继续使用热键 但现在我有一个问题 注册热键会禁用键盘上的按键 因此我只能将按键发送到
  • 为什么要使用指针? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我知道这是一个非常基本的问