views:

756

answers:

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

    }
+12  A: 
  • pName[0] is the first element in a character array (one character)
  • pName is a shortcut to &pName[0] (a pointer to the first element of your array)

The reason you are getting your error is because strcpy expects a pointer to a char (char*), and not a char value (which is what pName[0] is)

Daniel
Matthew Scharley
so [] operator on pointer does 2 things dereference and addition?
yesraaj
@yesraaj: Yes. pName[5] is the same thing as *(pName + 5).
Pedro d'Aquino
yesraaj: arrayPointer[1] is the same as *(arrayPointer + 1). The latter is "increment pointer so that it points to item at position 1 in the array, then dereference to get value pointed to".
Skurmedel
Johannes Schaub - litb
A: 

There is no difference. They will both crash since you've not allocated any space for pName. :)[EDIT: No longer a crash - question has been edited]

The main difference is a stylistic one, frequently influenced by which fits the way the surrounding code is written - mostly array access or mostly pointer access.

(EDIT: assuming you really meant &pName[0] as Brian Bondy pointed out.)

Steve Fallows
A: 

Technically, strcpy(pName[0], dummy); isn't correct. Even if memory was allocated for it.

This is because pName[0] is of type 'char' whilst pName + 0 is of type char*. They both reference the same memory, but in different ways.

The compiler can then turn strcpy(pName[0], dummy); into strcpy((char*) pName[0], dummy); which is a dangerous implicit cast. If your compiler is half decent you'll get a warning or error (As you are seeing with your "error C2664").

Matthew Iselin
A: 

An array is simply a pointer automatically (usually) assigned to an automatically allocated block of memory. Taking your example, you can declare dummy equally as:

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

And you can then use either array syntax or pointer syntax to access the data:

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

Both [] and * can be used de re-reference pointers and arrays, so the following are equivalent:

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

Given the second form, (ptr + N) is still a pointer, just further along the array. This is why it is syntactically correct in your example. ptr[N] is a de-referencing of the pointer and is a char (in this context).

Sean Johnston
A: 

pName is pointer to newly allocated memory. char *pName = new char[10];

dummy is also an array/pointer. char dummy[] = "dummy";

pName is pointer and pointing to base address, even you add (pName + 0) is still pointing to same memory location, becuase your only adding 0. strcpy(pName + 0,dummy);

strcpy use pointer variable, and your passing value in first argument, therefore your are getting error strcpy(pName[0],dummy)

Syed Tayyab Ali
+2  A: 

When dealing with pointers and arrays in C or C++ it really helps to recognize them as very distinct constructs (I think one of the best books that explains this distinction is a book called "Deep C Secrets" if i remember correctly). What muddies the waters is the fact that there is a one way silent conversion allowed from array-names to pointers (an inconsistency in the language's handling of variable names) - but it is very important not to interpret the existence of this decay phenomenon as implying equivalence.

To help us reason about this, let us introduce the idea of a 'memory cell'. We model a 'memory cell' as having two attributes:

a) value
b) address

We can then model a simple C++ variable as having two attributes (we do not need types at this low level of abstraction):

c) name  
d) memory cell

Like most models, it has some deficiencies (does not deal with an array with more than one element, but it is sufficient for our purposes).

So for example:

// 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...

Now here's the main difference between an array variable and a non-array (pointer) C++ variable:

When a variable name in C++ is evaluated, it always evaluates to the value of its memory cell with one exception: if the variable names an array variable.
If the variable is the name of an array it evaluates to the address of the memory cell.
The above two lines are worth reading again.

Here are some examples to help clarify the implications (refer to the above variables):

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

This in no way should imply that an array variable is the same as a pointer variable.
They have inherently different types and any attempt to treat them as the same (i.e. define a variable name as an array in one translation unit, and as a pointer in another) will result in bad things happening.

So for e.g. do not do this:

// 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

I hope this helps. If you still feel that further clarification might help, please ask a followup question, and don't hesitate to get a copy (library?) of that "Deep C Secrets" book :)

--
p.s. function types and their names and their decay are irrelevant to most of this post
p.s. I have also intentionally left out that the array-to-pointer conversion does not occur when arrays are bound to reference types

Faisal Vali
+1, nice one. i think your definition of "variable" matches the one of C++, too, which says: "A variable is introduced by the declaration of an object. The variable’s name denotes the object." These are the two properties of a variable that you define: name, and memory cell (object == region of storage with associated properties (type, storage duration, is-alive, ...), memory cell = start of that region).
Johannes Schaub - litb