指针数组和数组指针的区别?

2024-05-14

 char string1[3][4]={"koo","kid","kav"}; //This is a 2D array

 char  * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
 char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters

//I want to know differences between string1Ptr(pointer to array mentioned in question) and string(array of pointers mentioned in question). I only typed string1 here to give string1Ptr an address to strings

除此之外,string可以指向任何大小的字符串string1Ptr只能指向大小为 4 的字符串(否则指针算术会出错),我看不出它们之间有任何区别。

例如,

   printf("%s\n", string1[2]);   // All print the same thing, ie, the word "kav"
   printf("%s\n", string1Ptr[2]);
   printf("%s\n", string[2]);

它们似乎都执行相同的指针算术。(我假设的原因string and string1Ptr除了我上面提到的差异之外,几乎相似)

那么string和string1Ptr有什么区别呢?有什么理由使用其中一种而不是另一种?

PS:我是个新手,请多多包涵。 另外,我确实检查过C 指向数组/指针数组的指针消歧 https://stackoverflow.com/q/859634/10701114,似乎没有回答我的问题。


char string1[3][4]={"koo","kid","kav"}; //This is a 2D array

char  * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters

除此之外,string可以指向任何大小的字符串string1Ptr只能指向大小为 4 的字符串(否则 指针算术会出错),我没有任何区别 他们。

它们是绝对的、根本上的不同,但 C 费尽心思向你隐藏这种区别。

string is an array。它标识存储其元素的连续内存块。这些元素恰好是类型char *在此示例中,但这只是一个相对较小的细节。我们可以将这里比作一栋包含多个房间的房子——这些房间实际上是房子的一部分,并且存在于房子的物理边界之内。我可以随心所欲地装饰房间,但它们始终是那所房子的房间。

string1Ptr is a pointer。它标识一个内存块,其内容描述如何访问另一个不同的内存块,其中包含 4 个数组chars 驻留。在我们的房地产类比中,这就像一张纸,上面写着“42 C Street,主卧室”。使用该信息,您可以找到房间并根据需要重新装饰它,就像其他情况一样。但你也可以用不同房间的定位器(也许在不同的房子里)或随机文本替换纸张,或者你甚至可以烧掉整个信封,而不会影响 C 街的房间。

string1就其本身而言,是一个数组的数组。它标识存储其元素的连续内存块。每个元素本身就是一个由 4 组成的数组chars,顺便说一句,它恰好是对象的类型string1Ptr可以指点一下。

例如,

printf("%s\n", string1[2]);   // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);

它们似乎都执行相同的指针算术。(我的原因 假设string and string1Ptr除了以下方面几乎相似 我上面说的区别)

... and that is where C hiding the distinction comes in. One of the essential things to understand about C arrays is that in nearly all expressions,* values of array type are silently and automatically converted to pointers [to the array's first element]. This is sometimes called pointer "decay". The indexing operator is thus an operator on pointers, not on arrays, and indeed it does have similar behavior in your three examples. In fact, the pointer type to which string1 decays is the same as the type of string1Ptr, which is why the initialization you present for the latter is permitted.

但您应该明白,这三种情况下操作的逻辑顺序并不相同。首先,考虑

printf("%s\n", string1Ptr[2]);

Here, string1Ptr是一个指针,索引运算符直接适用于该指针。结果相当于*(string1Ptr + 2),其类型为char[4]。作为数组类型的值,它被转换为指向第一个元素的指针(导致char *).

现在考虑

printf("%s\n", string1[2]);

string1是一个数组,因此首先将其转换为指向其第一个元素的指针,从而得到一个类型的值char(*)[4]。这与以下类型相同string1Ptr1,并且如上所述进行相应的评估。

但这一个有点不同:

printf("%s\n", string[2]);

Here, string是一个指针,因此索引操作直接应用于它。结果相当于*(string + 2),其类型为char *。不执行自动转换。

有什么理由使用其中一种而不是另一种?

很多,双向的,具体取决于您当时的特定需求。一般来说,指针更灵活,特别是因为它们需要使用动态分配的内存。但他们却面临着以下问题

  • 指针可能在范围内,但不指向任何东西,并且
  • 声明一个指针并不会创建任何它指向的东西。还,
  • 即使一个指针在程序执行过程中一度指向某个东西,并且它的值随后没有被程序写入,它仍然可以停止指向任何东西。 (这通常是由于指针比它所指向的对象寿命更长的结果。)

此外,它既可以是优点,也可以是缺点

  • 指针在其生命周期内可以任意次数地被自由地指定为指向新对象。

一般来说,数组更容易用于多种用途:

  • 声明数组为其所有元素分配空间。您可以选择在声明时为它们指定初始值,或者在某些(但不是全部)情况下利用默认初始化。
  • 数组的标识符是有效的,并且引用数组位于范围内的任何位置。
  • 或者,如果提供了初始值设定项,则数组声明可以使用它来自动确定数组维度。

* But only nearly all. There are a few exceptions, with the most important being the operand of a sizeof operator.

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

指针数组和数组指针的区别? 的相关文章

  • Qt - QProcess 不工作

    我尝试启动 Internet Explorer 所以我使用下面的代码 QProcess process new QProcess this QString temp C Program Files Internet Explorer iex
  • 尝试了解使用服务打开对话框

    我已经阅读了有关使用 mvvm 模式打开对话框的讨论 我看过几个使用服务的示例 但我不明白所有部分如何组合在一起 我发布这个问题寻求指导 以了解我应该阅读哪些内容 以更好地理解我所缺少的内容 我将在下面发布我所拥有的内容 它确实有效 但从我
  • C# 方法重载决策不选择具体的泛型覆盖

    这个完整的 C 程序说明了这个问题 public abstract class Executor
  • 转换 const void*

    我有一个函数返回一个const void 我想用它的信息作为char 我可以将它投射为 C 风格的罚款 char variable但是当我尝试使用reinterpret cast like reinterpret cast
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 如何将 .txt 文件中的数据转换为 xml? C#

    我在一个文本文件中有数千行数据 我想通过将其转换为更容易搜索的内容来轻松搜索 我希望 XML 或其他类型的大型数据结构 尽管我不确定它是否是最好的对于我的想法 每行的数据如下所示 第 31 册 托马斯 乔治 32 34 154 每本书都不是
  • RestSharp获取序列化输出

    我正在寻找一种方法来访问 AddBody 调用的序列化结果 我正在使用内置的 RestSharp 序列化器 例子 class Foo public string FooField void SendRecord var f new Foo
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • 不同 C++ 文件中的相同类名

    如果两个 C 文件具有相同名称的类的不同定义 那么当它们被编译和链接时 即使没有警告也会抛出一些东西 例如 a cc class Student public std string foo return A void foo a Stude
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 在 C# 中为父窗体中的子窗体控件添加事件处理程序

    我有两种形式 一种是带有按钮和文本框的父表单 单击该按钮时 将打开一个对话框 该子窗体又包含一个文本框和一个按钮 现在我想要的是 每当子表单文本框中的文本更改时 父表单文本框中的文本会自动更改 为了获得这个 我所做的是 Form3 f3 n
  • 将二变量 std::function 转换为单变量 std::function

    我有一个函数 它获取两个值 x 和 y 并返回结果 std function lt double double double gt mult double x double y return x y 现在我想得到一个常量 y 的单变量函数
  • 将函数参数类型提取为参数包

    这是一个后续问题 解包 元组以调用匹配的函数指针 https stackoverflow com questions 7858817 unpacking a tuple to call a matching function pointer
  • 如何最好地以编程方式将 `__attribute__ ((unused))` 应用于这些自动生成的对象?

    In my makefile我有以下目标 它将文本 HTML 资源 编译 为unsigned char数组使用xxd i http linuxcommand org man pages xxd1 html 我将结果包装在匿名命名空间和标头保
  • 模板类中的无效数据类型生成编译时错误?

    我正在使用 C 创建一个字符串类 我希望该类仅接受数据类型 char 和 wchar t 并且我希望编译器在编译时使用 error 捕获任何无效数据类型 我不喜欢使用assert 我怎样才能做到这一点 您可以使用静态断言 促进提供一个 ht
  • 将 Lambda 表达式树与 IEnumerable 结合使用

    我一直在尝试了解有关使用 Lamba 表达式树的更多信息 因此我创建了一个简单的示例 这是代码 如果作为 C 程序粘贴到 LINQPad 中 它可以工作 void Main IEnumerable
  • 在 Win32 控制台应用程序中设置光标位置

    如何在 Win32 控制台应用程序中设置光标位置 最好 我想避免制作句柄并使用 Windows 控制台功能 我花了整个早上沿着那条黑暗的小巷跑 它产生的问题比它解决的问题还要多 我似乎记得当我在大学时使用 stdio 做这件事相对简单 但我
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2

随机推荐