在以下上下文中指针和数组有什么区别?

时间:2009-06-26 12:00:27

标签: c++ arrays pointers strcpy

#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 *'

    }

6 个答案:

答案 0 :(得分:12)

  • pName [0]是字符数组中的第一个元素(一个字符)
  • pName是&amp; pName [0]的快捷方式(指向数组第一个元素的指针)

你得到错误的原因是因为strcpy需要一个指向char(char *)的指针,而不是char值(这是pName [0]是什么)

答案 1 :(得分:3)

当用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

这绝不应该暗示数组变量与指针变量相同
它们具有固有的不同类型,并且任何将它们视为相同的尝试(即将变量名称定义为一个转换单元中的数组,并将其作为指针放在另一个转换单元中)将导致不良事件发生。< / p>

因此,例如不要这样做:

// myproj_file1.cpp
int array[100] = { 0 }; // here 'array' evaluates to the *address* of the first memory cell

// myproj_file2.cpp
extern int* array; // here 'array' evaluates to the *value* of the first memory cell 
            // Assuming the linker links the two
            // what it does if you read the assembly, is something like this: 
            // extern int* array = (int*) array[0];
            // but it doesn't have to, it can do anything, since the behavior is undefined

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

-
附:功能类型及其名称及其衰减与此帖的大部分内容无关 附:我还故意忽略了当数组绑定到引用类型

时,不会发生数组到指针的转换

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

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

然后,编译器可以将strcpy(pName[0], dummy);转换为strcpy((char*) pName[0], dummy);,这是一个危险的隐式转换。如果你的编译器是一半体面的,你会收到警告或错误(正如你所看到的那样“错误C2664”)。

答案 4 :(得分:0)

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

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

[]*都可用于重新引用指针和数组,因此以下内容是等效的:

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

鉴于第二种形式,(ptr + N)仍然是一个指针,就在数组的前面。这就是为什么它在您的示例中在语法上是正确的。 ptr[N]是指针的解引用,是一个char(在此上下文中)。

答案 5 :(得分:0)

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

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

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

strcpy使用指针变量,以及你在第一个参数中的传递值,因此你得到错误strcpy(pName[0],dummy)