Во-первых, это объявление
const char * arr[2] = "foo";
неверно. Массивы являются агрегатами, и инициализаторы их элементов должны быть заключены в фигурные скобки.
const char * arr[2] = { "foo" };
Используемый в выражениях массив (за редкими исключениями) преобразуется в указатель типа const char **
.
Эта функция
void func(char ** a)
{
// Do some stuff...
}
не принимает указатель на указатель на постоянные данные. Это означает, что функция может изменять указанные данные. Это, в свою очередь, означает, что вы не должны передавать свой массив этой функции.
Что вы могли бы сделать, так это динамически выделить массив массивов, например,
char **p = new char *[2];
for ( size_t i = 0; i < 2; i++ )
{
p[i] = new char[4];
}
strcpy( p[0], "foo" );
strcpy( p[1], "bar" );
func( p );
for ( size_t i = 0; i < 2; i++ )
{
delete[] p[i];
}
delete[] p;