Я пытаюсь понять следующую ситуацию:
У нас есть объявление константной переменной pfPowerManStates
указателя типа на const PowerManStateType
. PowerManStateType
- указатель на функцию - uint8 (*PowerManStateType)(void);
Другими словами, pfPowerManStates
является константным указателем на константную переменную типа указатель функции. определение pfPowerManStates
:
const PowerManStateType* const pfPowerManStates = &(pfStates[0]);
И он указывает на массив, полный указателей на функции
Все идет нормально. Но позже я вижу следующее утверждение:
NewPowerModeL = pfPowerManStates[CurrentPowerMode]();
Здесь мы присваиваем значение pfPowerManstate
некоторой переменной. Так что я не могу обернуть это вокруг своей головы. Разве наличие двух const
ключевых слов в объявлении не означает, что мы можем ПРОЧИТАТЬ только первое значение массива (&(pfStates[0])
? Я понимаю следующее: У меня есть константный указатель типа константный указатель на функцию, которая принимает (void) аргументы и возвращает int. Для своего объявления этот константный указатель получает значение адреса первой функции в массиве функций pfStates[X]
, а поскольку его const, мы не можем указать на другую функцию в массиве pfStates[X]
. Я очень запутался в этом пункте, прочитал пост 5 раз и стал еще более запутанным, поэтому я просто опубликую его и надеюсь на лучшее. Спасибо.
3 ответа
Краткое содержание:
const T *p; // p is writable, *p is not
T const *p; // same as above
выражение *p
имеет тип const T
, поэтому вы не можете присвоить новое значение *p
(вы не можете писать в точку p
) к ) . Однако вы можете присвоить новое значение p
, указав его для другого объекта const T
. p
- это не const
указатель на объект const
.
T * const p; // *p is writable, p is not
Выражение *p
имеет тип T
, поэтому оно доступно для записи - вы можете обновить значение того, на что указывает p
. Однако сам указатель p
имеет тип T * const
, поэтому его нельзя записать - нельзя установить p
для указания на другой объект. p
- это const
указатель на не - const
объект.
const T * const p; // neither p nor *p are writable
T const * const p; // same as above
В этом случае *p
имеет тип const T
, а p
имеет тип const T * const
- ни один не может быть записан в. p
- это const
указатель на объект const
.
В данном конкретном случае:
const PowerManStateType* const pfPowerManStates = &(pfStates[0]);
pfPowerManStates
указывает на первый элемент массива, который выглядит как указатель на функцию. Поскольку pfPowerManStates
сам по себе является указателем, вы можете использовать оператор []
для него как массив и, таким образом, читать элементы из массива. Однако вы не можете изменить ни один из элементов через pfPowerManStates
, а также не можете установить его так, чтобы он указывал на другой объект.
Заявление
NewPowerModeL = pwPowerManStates[CurrentPowerMode]();
Можно разбить на более мелкие части:
PowerManStateType temporary_function_pointer = pwPowerManStates[CurrentPowerMode];
NewPowerModeL = temporary_function_pointer();
Поэтому вы не присваиваете значение pwPowerManStates
переменной NewPowerModeL
, вместо этого вы разыменовываете указатель pwPowerManStates
, чтобы получить один элемент. Этот элемент является указателем на функцию. И затем вы вызываете эту функцию, чтобы получить значение, присваиваемое NewPowerModeL
.
Также обратите внимание, что
NewPowerModeL = pwPowerManStates[CurrentPowerMode]();
Должно быть эквивалентно
NewPowerModeL = pfStates[CurrentPowerMode]();
Указатель const
не мешает его индексировать (т.е. использовать в качестве массива) или использовать в арифметике указателя. Вы не можете изменить только указатель.
Ниже у вас есть немного более понятный код.
#include <stdio.h>
const int array[] = {1,2,3,4,5,6,7,8,9,10};
const int *const constptr = array;
int pick(const int *const ptr, int index)
{
return ptr[index];
}
int pick1(const int *const ptr, int index)
{
return *(ptr + index);
}
int main()
{
for(int x = 0; x < sizeof(array) / sizeof(array[0]); x++)
{
printf("x = %d constptr[%d] == %d\n", x, x, pick(constptr, x));
printf("x = %d constptr + %d == %d\n", x, x, pick1(constptr, x));
}
}
Похожие вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.