Почему эти типы указателей несовместимы?

У меня есть предупреждение компиляции в gcc о «несовместимом типе указателя» со следующим кодом:

f(unsigned char** arr)
{
   unsigned char* p = *arr;
}

int main()
{
   unsigned char a[31];
   f(&a);
}

Хотелось бы понять почему и как это исправить.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
132
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Выражение &a имеет тип «указатель на массив unsigned char размера 31», т.е. unsigned char (*)[31] это отличается от объявленного параметра unsigned char **, и первый не может быть преобразован во второй.

Предположительно, вы хотите работать с массивом изнутри функции. В этом случае просто измените тип параметра на unsigned char * и передайте a непосредственно в функцию:

void f(unsigned char *arr)
{
   unsigned char *p = arr;
}

int main()
{
   unsigned char a[31];
   f(a);
}

Это разрешено, поскольку массив при использовании в выражении (кроме операнда &) превращается в указатель на свой первый элемент. В частности, массив типа unsigned char[31] распадается на указатель типа unsigned char * при передаче функции.

Чтобы проиллюстрировать это, можно попробовать сравнить sizeof( *(&a) ) и ``sizeof( *p )`: godbolt.org/z/xe1f7zGcW

Eugene Sh. 08.08.2024 18:46

У вас уже есть ответ в дюпе.

user12002570 08.08.2024 18:50
Ответ принят как подходящий

a — это массив из 31 unsigned char (unsigned char[31]).

&a — указатель на такой массив (unsigned char (*)[31]).

Вы пытаетесь «присвоить» это arr, что является указателем на указатель на unsigned char.

&a не указывает на указатель. &a несовместим с unsigned char **.


Обычный подход: (Указатель на первый элемент)

void f( unsigned char *arr ) {
   unsigned char *p = arr;
}

int main( void ) {
   unsigned char a[31];
   f( a );  // Short for `f( &(a[0]) )`.
}

Альтернативный подход: (Указатель на массив)

void f( unsigned char (*arr)[31] ) {
   unsigned char *p = *arr;    // Short for `p = &((*arr)[0])`.
}

int main( void ) {
   unsigned char a[31];
   f( &a );
}

Второй вариант хорош, но что делать, если я не хочу указывать размер массива?

user180574 08.08.2024 18:47

@user180574 void f( size_t n, unsigned char (*arr)[n] )

ikegami 08.08.2024 18:48

Это работает с gcc, но g++ жалуется на «ошибку: использование параметра вне тела функции перед токеном ‘]’»

user180574 08.08.2024 18:50

Вы сказали, что используете C, но g++ не является компилятором C. Не пытайтесь скомпилировать код C с помощью g++.

ikegami 08.08.2024 18:51

Другие вопросы по теме