Qual é a diferença entre o ponteiro e matriz no seguinte contexto?
Pergunta
#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 *'
}
Solução
- pname [0] é o primeiro elemento em uma matriz de caracteres (1 personagem)
- Pname é um atalho para & pname [0] (um ponteiro para o primeiro elemento da sua matriz)
A razão pela qual você está recebendo seu erro é porque o strcpy espera um ponteiro para um char (char*), e não um valor de char (que é o que é o pname [0])
Outras dicas
Ao lidar com ponteiros e matrizes em C ou C++ que realmente ajuda a reconhecê-los como muito distinto construções (eu acho que um dos melhores livros que explica esta distinção é um livro chamado "Deep C Segredos" se eu me lembro corretamente).O que confunde as águas é o fato de que existe uma maneira silenciosa de conversão permitida a partir da matriz de nomes para ponteiros (uma inconsistência na linguagem de manipulação de nomes de variáveis), mas é muito importante não interpretar a existência de decadência como um fenómeno que implica equivalência.
Para nos ajudar a raciocinar sobre isso, vamos apresentar a ideia de uma "célula de memória'.Temos o modelo de uma "célula de memória' como tendo dois atributos:
a) value
b) address
Podemos, então, um modelo simples em C++ variável como tendo dois atributos (nós não precisamos de tipos em que este baixo nível de abstração):
c) name
d) memory cell
Como a maioria dos modelos, tem algumas deficiências (não lidar com uma matriz com mais de um elemento, mas é suficiente para os nossos propósitos).
Assim, por exemplo:
// 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...
Agora aqui está a principal diferença entre uma variável de array e um não array (ponteiro) variável C++:
Quando um nome de variável em C++ é avaliado, ele sempre avalia o valor da célula de memória com uma exceção:se os nomes de variáveis uma variável de matriz.
Se a variável é o nome de uma matriz avalia a endereço da célula de memória.
As duas linhas acima vale a pena ler de novo.
Aqui estão alguns exemplos para ajudar a esclarecer as implicações (consulte as variáveis acima):
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
Isto não deve implicar que uma variável de matriz é o mesmo como uma variável de ponteiro.
Eles têm inerentemente diferentes tipos e qualquer tentativa de tratá-los como a mesmo (i.é.definir um nome de variável como uma matriz em uma unidade de tradução, e como um ponteiro em outro), vai resultar em coisas ruins acontecendo.
Assim, por exemplo:não faça isso:
// 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
Espero que isso ajude.Se você ainda sentir que de mais esclarecimentos podem ajudar, por favor, pergunte a um acompanhamento questão, e não hesite em obter uma cópia (biblioteca?) de que "Profundo C Segredos", o livro :)
--
p.s.função de tipos e os seus nomes e a sua decadência são irrelevantes para a maioria este post
p.s.Eu também intencionalmente deixada de fora que a matriz-para-ponteiro de conversão não ocorre quando as matrizes são vinculados a tipos de referência
Tecnicamente, strcpy(pName[0], dummy);
não está correto. Mesmo que a memória fosse alocada para isso.
Isto é porque pName[0]
é do tipo 'char' enquanto pName + 0
é do tipo char*. Ambos fazem referência à mesma memória, mas de maneiras diferentes.
O compilador pode então virar strcpy(pName[0], dummy);
em strcpy((char*) pName[0], dummy);
que é um elenco implícito perigoso. Se o seu compilador for meio decente, você receberá um aviso ou erro (como está vendo com o seu "Erro C2664").
Não há diferença. Ambos vão travar, pois você não alocou nenhum espaço para o PNAME. :) [Editar: Não é mais um acidente - a pergunta foi editada
A principal diferença é estilística, freqüentemente influenciada pela qual se encaixa na maneira como o código circundante é escrito - principalmente acesso à matriz ou acesso principalmente ao ponteiro.
(Editar: assumindo que você realmente quis dizer e Pname [0] como Brian Bondy apontou.)
Uma matriz é simplesmente um ponteiro automaticamente (geralmente) atribuído a um bloco de memória alocado automaticamente. Levando seu exemplo, você pode declarar dummy igualmente como:
char dummy[] = "dummy";
char *dummy = "dummy";
E você pode usar a sintaxe da matriz ou a sintaxe do ponteiro para acessar os dados:
char ch = dummy[0]; // get the first element of the array
char ch = *dummy; // get the data pointed to by dummy
Ambos []
e *
Pode ser usado de referência e matrizes de referência, portanto, os seguintes são equivalentes:
array[N];
*(ptr + N);
Dada a segunda forma, (ptr + N)
ainda é um ponteiro, apenas mais longe ao longo da matriz. É por isso que está sintaticamente correto em seu exemplo. ptr[N]
é uma des-referência do ponteiro e é um char (neste contexto).
O PNAME é um ponteiro para a memória recém -alocada. char *pName = new char[10];
Dummy também é uma matriz/ponteiro. char dummy[] = "dummy";
O PNAME é ponteiro e aponta para o endereço base, até você adiciona (Pname + 0) ainda está apontando para o mesmo local de memória, porque você adiciona apenas 0. strcpy(pName + 0,dummy);
StrCpy Use a variável de ponteiro e seu valor de aprovação no primeiro argumento, portanto, você está recebendo erro strcpy(pName[0],dummy)