10

I have what I thought should be a very simple snippet of code to write, though I'm unable to compile for a reason which I do not understand.

The following simplified code will not compile:

char buffer[9] = "12345678";
char* pBuffer = &buffer;

Compiler (g++) throws the following error:

error: cannot convert 'char (*)[9]' to 'char*' in initialization

C++ isn't exactly my "native" language, but everywhere I've looked tells me this should work. Any ideas or advice is greatly appreciated.

Daniel S
  • 103
  • 1
  • 5

6 Answers6

20

Instead of taking the address of the array, write

char buffer[9] = "12345678";
char *pBuffer = buffer;

Edit: What does it all mean?

  • An array of type T of length n is a (contiguous) sequence of n T's in memory.

  • A pointer is a memory address.

So for example, the following code

char a[5] = "hello";
char *p = "world";

corresponds to the following situation in memory:

Comparing an array to a pointer.

In your code, you have created an array

char buffer[9] = "12345678";

in just the same way as the array char a[5] = "hello" was created. You intend to create a pointer char * which points to the first character of the array, just as char *p above points to the first character of the array "world".

When an expression of type "array of type" (here buffer) is used, it always "decays" to a pointer to the first element unless

1. the expression is used as the operand of sizeof (in sizeof(buffer), buffer does not decay to a pointer)

2. the expression is used as the operand of unary & (in &buffer, buffer does not decay to a pointer)

or

3. the expression is a string literal initializer for a character array (in char someBuffer[3] = "ab", the string literal "ab", an array, does not decay to a pointer).

This is laid out in section 6.2.2.1 of the standard:

729 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object and is not an lvalue.

As a result, all that you need to do to create a pointer char *pBuffer to the first character in your array is write

char *pBuffer = buffer;
Nate Chandler
  • 4,533
  • 1
  • 23
  • 32
  • Nate,This worked - thank you very much. Although, I'm still wondering... why? What exactly is the difference in syntax causing? Edit: still getting used to this board, removed my additional question. – Daniel S Jan 07 '13 at 04:52
  • 2
    @DanielS for a tl;dr: an array decays to a pointer to the first element. Taking the address of an array makes a pointer to an _array_ (which is a distinct type), not a pointer to the first element of that array. So arrays convert directly to pointers. – Seth Carnegie Jan 07 '13 at 05:11
  • Pointer are used to hold memory addresses. An array variable name is a pointer to first byte of consecutive memory location. in your case buffer is a special pointer that hold address for first byte of character array. So, you can assign it directly as in accepted answer. – Asad kamran Jan 07 '13 at 11:21
  • @NateChandle Now it become nice answer! Good explained – Grijesh Chauhan Jan 07 '13 at 16:17
12
  • The declaration char buffer[9] = "12345678"; creates an array of 9 chars.
    Here, buffer is the address of its first element but not of the array.

  • char* pBuffer = buffer; is a correct expression as pBuffer is a pointer to char and can address the first element.

  • But the expression char* pBuffer = &buffer is wrong, because pBuffer can't address an array. (error in your code, &buffer address of array as explained below)

Difference between buffer and &buffer

&buffer means address of array. The values of buffer and &buffer are really the same, but semantically both are different. One is an address of a char, while the other is an address of an array of 9 chars.

buffer[9] = "12345678";


+----+----+----+---+---+----+----+----+---+----+ 
| '1'| '2' |'3'|'4'|'5'| '6'| '7'|'8' | 0 |  ...........
+----+----+----+---+---+----+----+----+---+---+----+  
 201   202  203 204 205 206  207   208 209 210  211
  ^     ^                                         
  |     |                                         
(buffer) (buffer + 1)                                         
|                                         |
|-----------------------------------------|--------
|201                                      | 210
  ^                                          ^
  |                                          |
(&buffer)                                 (&buffer + 1)     

I used decimal numbers for address instead of hexadecimal

Even though the value of buffer is 201 and the value of &buffer is 201, their meaning is different:

  • buffer: first element's address—its type is char*.
  • &buffer: complete char array's address—its type is char(*)[9].

Additionally, to observe the difference, add 1 :

buffer + 1 gives 202 that is the address of the second array element '2' but
&buffer + 1 gives 210 which is the address of the next array.

On My System, I write following code:

int main(){
   char buffer[9] = "12345678";
   char (*pBuffer)[9] =  &buffer; 

   printf("\n %p, %p\n",buffer, buffer+1);
   printf("\n %p, %p\n",(&buffer), (&buffer+1));
}  

And the output is as below:

0xbfdc0343, 0xbfdc0344

0xbfdc0343, 0xbfdc034c

[ANSWER]

That's the reason Error is:

error: cannot convert 'char ()[9]' to 'char' in initialization

You are trying to assign 'char (*)[9]' type value to char*.

  • char (*ptr2)[9]; Here ptr2 is pointer to an array of 9 chars, And this time
    ptr2=&buffer is a valid expression.

How to correct your code?

As in Nate Chandler's answer:

char buffer[9] = "12345678";
char* pBuffer =   buffer;   

or another approach,

char buffer[9] = "12345678";
char (*pBuffer)[9] =  &buffer;       

Which you choose depends on what you need.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
4

array decays to pointer, you only need

char* pBuffer = buffer;

Also checkout: std::decay

   std::cout << "int[] -> int*; // " << std::boolalpha
              << std::is_same<int *, std::decay<int[]>::type>::value;

Output:

int[] -> int*; // true
billz
  • 44,644
  • 9
  • 83
  • 100
2

The error message is very clear; &buffer is of the type char (*)[9], i.e., a pointer to an array of char with 9 elements (yes, arrays are fully fledged types).

That is not the same as a char*. However, arrays degrade to pointers to the first element when needed, so...

char *pbuffer = buffer;
Ed S.
  • 122,712
  • 22
  • 185
  • 265
0

Name of array indicates it's base address, so if you just write buffer, it means address of buffer[0]. If you are using &buffer, you need to take it in char** not in char *.

So,

char* pBuffer = buffer;

Would be correct as suggested.

Pranit P Kothari
  • 326
  • 3
  • 11
-1

because the compiler can't implicitly convert char()[] to char. So you need explicit type conversion

char buffer[9] = "12345678";
char* pBuffer = (char*)&buffer;
slggamer
  • 217
  • 1
  • 2
  • 3
    Sure it works in this case, but I find the fact that you're promoting that you should just shut the compiler up instead of actually fixing the error a bit irritating. – chris Jan 07 '13 at 04:58
  • Yes, it is. But in this problem, I think the asker want to know why the compiler said "cannot convert". So I suggust the type conversion – slggamer Jan 07 '13 at 05:28
  • 1
    -1 Why in the world would you suggest taking the address of an array and casting it to a pointer to the first element when you could simply make the assignment correctly? I can cast something to whatever I want to, that doesn't make it correct or optimal. – Ed S. Jan 07 '13 at 06:07
  • @slggamer: Sure compiler will not give error for this, because C-Style casting this types of conversion, but this is not what we need to do. It will not serve the purpose. – Pranit P Kothari Jan 07 '13 at 06:20