Подтвердить что ты не робот

Проблема с указателем на массив символов С++

У меня есть то, что я думал, это очень простой фрагмент кода для написания, хотя я не могу скомпилировать по той причине, которую я не понимаю.

Следующий упрощенный код не будет компилироваться:

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

Компилятор (g++) выдает следующую ошибку:

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

С++ - это не совсем мой "родной" язык, но везде, где я смотрел, он говорит, что это должно работать. Любые идеи или советы приветствуются.

4b9b3361

Ответ 1

Вместо того, чтобы брать адрес массива, напишите

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

Изменить: что это значит?

  • Массив типа T длины n является (непрерывной) последовательностью n T в памяти.

  • Указатель - это адрес памяти.

Итак например, следующий код

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

соответствует следующей ситуации в памяти:

Comparing an array to a pointer.

В вашем коде вы создали массив

char buffer[9] = "12345678";

точно так же, как был создан массив char a[5] = "hello". Вы намереваетесь создать указатель char *, который указывает на первый символ массива, так же, как char *p выше указывает на первый символ массива "world".

Когда используется выражение типа "массив типа" (здесь buffer), оно всегда "распадается" на указатель на первый элемент, если

1. выражение используется как операнд sizeofsizeof(buffer), buffer не убывает указатель)

2. выражение используется как операнд unary &&buffer, buffer не распадается на указатель)

или

3. выражение является инициализатором строкового литерала для массива символов (в char someBuffer[3] = "ab", строковый литерал "ab", массив, не распадается на указатель).

Это выложено в в разделе 6.2.2.1 стандарта:

729 За исключением случаев, когда он является операндом оператора sizeof или унарного и оператора или является строковым литералом, используемым для инициализации массива, выражение, которое имеет тип "массив типа", преобразуется в выражение с указателем типа "pointer" для типа ", который указывает на начальный элемент объекта массива и не является значением l.

В результате все, что вам нужно сделать для создания указателя char *pBuffer для первого символа в вашем массиве, это написать

char *pBuffer = buffer;

Ответ 2

  • Объявление char buffer[9] = "12345678"; создает массив символов 9.
    Здесь buffer - это адрес его первого элемента, но не массива.

  • char* pBuffer = buffer; является правильным выражением, поскольку pBuffer является указателем на char и может обращаться к первому элементу.

  • Но выражение char* pBuffer = &buffer неверно, потому что pBuffer не может адресовать массив. (ошибка в вашем коде, &buffer адрес массива, как описано ниже)

Разница между buffer и &buffer

&buffer означает адрес массива. Значения buffer и &buffer на самом деле одинаковы, но семантически оба они разные. Один из них - адрес char, а другой - адрес массива из 9 символов.

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)     

Я использовал десятичные числа для адреса вместо шестнадцатеричного

Несмотря на то, что значение buffer равно 201, а значение &buffer равно 201, их значение отличается:

  • buffer: адрес первого элемента — его тип char*.
  • &buffer: полный char адрес массива — его тип char(*)[9].

Кроме того, чтобы наблюдать разницу, добавьте 1:

buffer + 1 дает 202, то есть адрес второго элемента массива '2', но
&buffer + 1 дает 210, который является адресом следующего массива.

В моей системе я пишу следующий код:

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));
}  

И вывод выглядит следующим образом:

0xbfdc0343, 0xbfdc0344

0xbfdc0343, 0xbfdc034c

[ANSWER]

Что причина Ошибка:

error: не может преобразовать 'char() [9]' в 'char' при инициализации

Вы пытаетесь присвоить значение типа 'char (*)[9]' char*.

  • char (*ptr2)[9]; Здесь ptr2 is pointer to an array of 9 chars, и на этот раз
    ptr2=&buffer является допустимым выражением.

Как исправить код?

Как и в ответе Нейт Чандлер:

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

или другой подход,

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

Что вы выбираете, зависит от того, что вам нужно.

Ответ 3

распадается на указатель, вам нужно только

char* pBuffer = buffer;

Также checkout: std:: decay

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

Вывод:

int[] -> int*; // true

Ответ 4

Сообщение об ошибке очень ясно; &buffer имеет тип char (*)[9], то есть указатель на массив из char с 9 элементами (да, массивы - это полноценные типы).

Это не то же самое, что char*. Однако при необходимости массивы делятся на указатели на первый элемент, поэтому...

char *pbuffer = buffer;

Ответ 5

Имя массива указывает его базовый адрес, поэтому, если вы просто пишете буфер, это означает адрес буфера [0]. Если вы используете & buffer, вам нужно взять его в char ** не в char *.

Итак,

char* pBuffer = buffer;

Было бы правильно, как было предложено.

Ответ 6

потому что компилятор не может неявно преобразовывать char() [] в char. Таким образом, вам требуется явно преобразование типов

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