Инициализация статического массива C и цикломатическая сложность

У меня есть следующий код:

typedef struct A_{

  void* values;
}A;

typedef struct C_{

  int array_C[3][3];
}C;

typedef struct B_{

  C c;
}B;

int main(void)
{
    B* b;

    A array_A[2] = {
                        {
                            &(b->c.array_C)   \\ line 23
                        },

                        {
                            &(b->c.array_C)    \\ line 27
                        }
                  };

   return 0;
}

моя ошибка находится в строках 23 и 27, в которых говорится, что &(b->c.array_C) должно быть константным. что я делаю неправильно? адрес массива не константа?

Причина, по которой я это делаю, заключается в том, что мне нужно улучшить цикломатическую сложность функции с помощью 340 операторов if, когда каждый оператор if имеет следующую форму:

if( exspretion )
{
   foo( address_of_array);
   return false;
}

если я изменю 340 операторов if на один цикл while, который выполняется 340 раз и получает из приведенного выше массива аргумент для функции foo, цикломатическая сложность будет лучше?


person IceCube    schedule 28.07.2014    source источник
comment
Проблема в том, что выражение &(b->c.array_C) требует, чтобы значение b было известно во время компиляции, а это не так.   -  person Drew McGowen    schedule 29.07.2014
comment
b — неинициализированный указатель. Сначала вы должны инициализировать его действительным адресом.   -  person Don't You Worry Child    schedule 29.07.2014
comment
Действительно ли это изменение улучшит ясность кода, или оно просто обманет инструмент, заставив его думать, что сложность упрощается, скрывая реальный код в массиве?   -  person Moby Disk    schedule 29.07.2014
comment
@DrewMcGowen Почему выражение требует, чтобы значение b было известно во время компиляции?   -  person Utkan Gezer    schedule 29.07.2014
comment
@ThoAppelsin просто выходит из упомянутого OP с предупреждением о том, что он должен быть постоянным   -  person Drew McGowen    schedule 29.07.2014
comment
В коде создайте как экземпляр B, так и указатель на B, в следующей строке инициализируйте указатель, установив его равным адресу экземпляра. (См. код ниже, слишком грязный для комментария).   -  person ryyker    schedule 29.07.2014
comment
Конечно, цикломатическая сложность была бы уменьшена, если бы 340 (!) операторов if были заменены одним оператором for на один оператор if внутри цикла, но это фактически сделало бы функцию (очень простым) интерпретатором большого массива. Другой подход, который вы могли бы использовать, - это сгенерировать код, например. с помощью Perl-скрипта из CSV-файла. Мой вопрос к вам будет заключаться в том, почему вы хотите уменьшить цикломатическую сложность в первую очередь? Ясность кода?   -  person rlc    schedule 29.07.2014
comment
@Andrey Isakov: Какой компилятор вы используете? Требование must be const присутствует только в C89/90. И очень немногие компиляторы C C89/90 фактически применяли это (честно говоря, сейчас я не знаю ни одного компилятора, который делал бы это по умолчанию). В компиляторе C C99 (или более поздней версии) такой ошибки не было бы. Требуется ли в вашем случае придерживаться архаичной спецификации C89/90?   -  person AnT    schedule 05.12.2016
comment
@ThoAppelsin: в современном C это не обязательно знать во время компиляции. Но в C89/90 это было. Все инициализаторы, заключенные в {}, в C89/90 должны были состоять из констант времени компиляции (даже при использовании с локальными объектами). Это требование было отменено в C99. Но большинство компиляторов C89/90 уже проигнорировали это требование, что заставляет меня задаться вопросом, какой компилятор использует OP.   -  person AnT    schedule 05.12.2016


Ответы (1)


Для устранения ошибки, которую вы видите, строка:

B* b;  

Можно изменить на:

B b, *pB;//create an instance of B, and a pointer to B at the same time. 
pB = &b; //now, pB is initialized to point at a real place in memory. (i.e. b)  
         //(use it instead of b in your code)  

Main теперь будет выглядеть так:

int main(void)
{
    B b, *pB;
    pB = &b;

    A array_A[2] = {
                        {
                            &(pB->c.array_C)   // line 23
                        },

                        {
                            &(pB->c.array_C)    // line 27
                        }
                  };
   //assignments can now be made to the actual array elements  
   pB->c.array_C[0][0]=3;//for example

   //Question:  How are you planning on using   array_A[0], array_A[1]?  (A is a void *)

   return 0;
}  

Относительно цикломатической сложности
и вашего вопроса:
...если я изменю 340 операторов if на один цикл while... цикломатический сложность будет лучше ?

цикломатическая сложность раздела исходного кода – это количество линейно независимых путей в исходном коде. Например, если исходный код не содержит точек принятия решений, таких как операторы IF или циклы FOR, сложность будет равна 1, поскольку в коде есть только один путь. (Из ЗДЕСЬ) )

Цикл for не будет улучшением по сравнению с 340 последовательными вызовами с точки зрения цикломатической сложности, но с точки зрения удобства сопровождения и удобочитаемости это будет большое улучшение.

person ryyker    schedule 28.07.2014