在以下上下文中,指针和数组有啥区别?

Posted

技术标签:

【中文标题】在以下上下文中,指针和数组有啥区别?【英文标题】:What is the difference between pointer and array in the following context?在以下上下文中,指针和数组有什么区别? 【发布时间】:2010-11-06 03:10:28 【问题描述】:
#include <cstring>
int main()
    
    char *pName = new char[10];
    char dummy[] = "dummy";
    strcpy(pName + 0,dummy);//how this is different from -->this works
    strcpy(pName[0],dummy);//this one...--> error C2664: 'strcpy' : 
                           //cannot convert parameter 1 
                           //from 'char' to 'char *'

    

【问题讨论】:

我想你的意思是 strcpy(&(pName[0]), dummy); 【参考方案1】: pName[0] 是字符数组中的第一个元素(一个字符) pName 是 &pName[0] 的快捷方式(指向数组第一个元素的指针)

您收到错误的原因是因为 strcpy 需要一个指向 char (char*) 的指针,而不是 char 值(这就是 pName[0] 的含义)

【讨论】:

so [] 指针上的操作符做了两件事取消引用和添加? @yesraaj:是的。 pName[5] 与 *(pName + 5) 相同。 yesraaj:arrayPointer[1] 与 *(arrayPointer + 1) 相同。后者是“递增指针,使其指向数组中位置 1 的项,然后取消引用以获取指向的值”。 +1,推向“好答案”徽章 :) 这对于 pName 是正确的。来自 silly litb 的一条注释:在所有情况下 dummy 都不是这样:“dummy”不是“&dummy[0]”的快捷方式。【参考方案2】:

在处理 C 或 C++ 中的指针和数组时,将它们识别为非常不同的结构确实很有帮助(如果我没记错的话,我认为解释这种区别的最好的书之一是一本名为“Deep C Secrets”的书)。搅浑水的是这样一个事实,即允许从数组名称到指针的单向静默转换(语言对变量名称的处理不一致) - 但重要的是不要将这种衰减现象的存在解释为暗示等价。

为了帮助我们对此进行推理,让我们介绍一下“记忆细胞”的概念。我们将“记忆单元”建模为具有两个属性:

a) value
b) address

然后我们可以将一个简单的 C++ 变量建模为具有两个属性(我们不需要这种低抽象级别的类型):

c) name  
d) memory cell

和大多数模型一样,它也有一些不足(不能处理包含多个元素的数组,但对于我们的目的来说已经足够了)。

例如:

// non-array variable: name 'i', and memory cell: value=3, address=0x0A
int i = 3;

// non-array variable: name 'p', and memory cell: value=0x0A, address=0x0B
int *p = &i;

// array variable: name 'a', and memory cell: vale=4, address=0x0C     
int a[1] =  4 ;

// non-array variable: name 'b', and memory cell: value=0x0C, address = 0x0D
int (*b)[1] = &a;

// non-array variable: name 's', and memory cell: value=0x0C, address = 0x0E
int *s = &a[0];


// non-array variable: name 't', and memory cell: value=0x0C, address = 0x0F
int *t = a; // Here is the key difference! read on...

现在这里是数组变量和非数组(指针)C++ 变量之间的主要区别:

当 C++ 中的变量名被计算时,它总是计算其内存单元的值,但有一个例外:如果变量命名为数组变量。 如果变量是一个数组的名称,它会计算为内存单元的地址。 以上两行值得再次阅读。

以下是一些有助于阐明含义的示例(请参阅上述变量):

int k = i;  // the 'i' name evaluates to the value of its cell, so 'k' is set to 3

int *q = p; // 'p' evaluates to the value of its cell, so 'q' is set to 0x0A

int *r = a; // 'a' evaluates to the *address* of its cell, so 'r' is set to 0x0C

int (*c)[1] = b; // 'c' is set to 0x0D

这绝不意味着数组变量与指针变量相同。 它们本质上具有不同的类型,任何将它们视为相同的尝试(即在一个翻译单元中将变量名定义为数组,在另一个翻译单元中定义为指针)将导致坏事发生。

所以例如不要这样做:

// myproj_file1.cpp 整数数组[100] = 0 ; // 这里 'array' 计算为第一个内存单元的 *address* // myproj_file2.cpp 外部 int* 数组; // 这里 'array' 计算为第一个内存单元的 *value* // 假设链接器链接了两者 // 如果你阅读程序集,它的作用是这样的: // extern int* array = (int*) array[0]; // 但它不是必须的,它可以做任何事情,因为行为是未定义的

我希望这会有所帮助。 如果您仍然认为进一步澄清可能会有所帮助,请提出后续问题,并毫不犹豫地获取“Deep C Secrets”一书的副本(库?):)

-- p.s.函数类型及其名称及其衰减与这篇文章的大部分内容无关 p.s.我还故意省略了当数组绑定到引用类型时不会发生数组到指针的转换

【讨论】:

+1,不错。我认为您对“变量”的定义也与 C++ 的定义相匹配,它说:“变量是由对象的声明引入的。变量的名称表示对象。”这些是您定义的变量的两个属性:名称和内存单元(对象 == 具有相关属性(类型、存储持续时间、是否处于活动状态,...)的存储区域,内存单元 = 该区域的开始) .【参考方案3】:

从技术上讲,strcpy(pName[0], dummy); 是不正确的。即使为它分配了内存。

这是因为pName[0] 是“char”类型,而pName + 0 是char* 类型。它们都引用了相同的内存,但方式不同。

然后编译器可以将strcpy(pName[0], dummy); 转换为strcpy((char*) pName[0], dummy);,这是一种危险的隐式转换。如果您的编译器还算不错,您将收到警告或错误(正如您在“错误 C2664”中看到的那样)。

【讨论】:

【参考方案4】:

没有区别。它们都会崩溃,因为您没有为 pName 分配任何空间。 :)[编辑:不再崩溃 - 问题已被编辑]

主要区别在于风格上的区别,它经常受到与周围代码编写方式相匹配的影响 - 主要是数组访问或主要是指针访问。

(编辑:假设您的意思是 &pName[0] 正如 Brian Bondy 指出的那样。)

【讨论】:

【参考方案5】:

数组只是一个自动(通常)分配给自动分配的内存块的指针。以您为例,您可以将 dummy 声明为:

char    dummy[] = "dummy";
char    *dummy = "dummy";

然后您可以使用数组语法或指针语法来访问数据:

char    ch = dummy[0];   // get the first element of the array
char    ch = *dummy;     // get the data pointed to by dummy

[]* 都可以用来de-re-reference 指针和数组,所以下面是等价的:

array[N];
*(ptr + N);

对于第二种形式,(ptr + N) 仍然是一个指针,只是沿着数组更远。这就是为什么在您的示例中它在语法上是正确的。 ptr[N] 是指针的取消引用,是一个字符(在此上下文中)。

【讨论】:

【参考方案6】:

pName 是指向新分配内存的指针。 char *pName = new char[10];

dummy 也是一个数组/指针。 char dummy[] = "dummy";

pName 是指向基地址的指针,即使你添加 (pName + 0) 仍然指向相同的内存位置,因为你只添加了 0。strcpy(pName + 0,dummy);

strcpy 使用指针变量,并且您在第一个参数中传递值,因此您收到错误 strcpy(pName[0],dummy)

【讨论】:

以上是关于在以下上下文中,指针和数组有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

在 SIMD 操作的上下文中,非压缩指令和压缩指令有啥区别?

在进程调度的上下文中调度程序和调度程序有啥区别

swift中快速框架中的描述和上下文有啥区别?

(a != b) 和 (a != (a = b) 有啥区别?

c#评级/面试题

在列表上下文中分配哈希有啥区别?