Проблема с указателем на массив символов С++
У меня есть то, что я думал, это очень простой фрагмент кода для написания, хотя я не могу скомпилировать по той причине, которую я не понимаю.
Следующий упрощенный код не будет компилироваться:
char buffer[9] = "12345678";
char* pBuffer = &buffer;
Компилятор (g++) выдает следующую ошибку:
error: cannot convert 'char (*)[9]' to 'char*' in initialization
С++ - это не совсем мой "родной" язык, но везде, где я смотрел, он говорит, что это должно работать. Любые идеи или советы приветствуются.
Ответы
Ответ 1
Вместо того, чтобы брать адрес массива, напишите
char buffer[9] = "12345678";
char *pBuffer = buffer;
Изменить: что это значит?
Итак например, следующий код
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.
выражение используется как операнд sizeof (в sizeof(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;