Я пытаюсь понять следующую ситуацию:

У нас есть объявление константной переменной 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 раз и стал еще более запутанным, поэтому я просто опубликую его и надеюсь на лучшее. Спасибо.

0
Krasimir Yordanov 5 Фев 2020 в 16:24

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, а также не можете установить его так, чтобы он указывал на другой объект.

2
John Bode 5 Фев 2020 в 15:28

Заявление

NewPowerModeL = pwPowerManStates[CurrentPowerMode]();

Можно разбить на более мелкие части:

PowerManStateType temporary_function_pointer = pwPowerManStates[CurrentPowerMode];
NewPowerModeL = temporary_function_pointer();

Поэтому вы не присваиваете значение pwPowerManStates переменной NewPowerModeL, вместо этого вы разыменовываете указатель pwPowerManStates, чтобы получить один элемент. Этот элемент является указателем на функцию. И затем вы вызываете эту функцию, чтобы получить значение, присваиваемое NewPowerModeL.


Также обратите внимание, что

NewPowerModeL = pwPowerManStates[CurrentPowerMode]();

Должно быть эквивалентно

NewPowerModeL = pfStates[CurrentPowerMode]();
3
Some programmer dude 5 Фев 2020 в 13:33

Указатель 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));
    }
}
1
P__J__ 5 Фев 2020 в 14:18