Существующие ответы, хотя и правильные, не дают четкого объяснения тому, что существует фундаментальная причина (кроме языковых правил), почему вы не можете привести char [10][10]
к char **
.Даже если вы заставите актеров произнести что-то вроде
char arr[2][2];
char ** ptr = (char **)arr;
, на самом деле это не сработает.
Причина в том, что в C и C ++ двумерный массив размещается в памяти как массив массивов.То есть, в C двумерный массив размещается в памяти как одно выделение,
arr -> arr[0][0]
arr[0][1]
arr[1][0]
arr[1][1]
Вы заметите, что arr
указывает не на char *
, а на arr[0][0]
который является char
;следовательно, хотя arr
может быть приведено к char *
, оно не может быть приведено к char **
.
Правильное принудительное приведение будет
char arr[2][2];
char * ptr = (char *)arr;
Если вы не хотите принудительно применять приведение (всегда хорошая идея, если это возможно!), Вы скажете
char arr[2][2];
char * ptr = arr[0];
или, чтобы сделать результат более понятным,
char arr[2][2];
char * ptr = &arr[0][0];
И теперь у вас есть (фактически) указатель на массив из 4 символов.[Proviso: Я не могу найти ничего в стандарте C, который запрещает реализации добавлять отступы между двумя строками массива, но я не верю, что это делают какие-либо реальные реализации, и обычная практика кодирования зависит от предположениячто такого дополнения не будет.]
Если вам действительно нужно преобразовать arr
в char **
, вам придется явно создать массив указателей:
char arr[2][2]
char * arr_ptrs[2];
char ** ptr;
arr_ptrs[0] = arr[0];
arr_ptrs[1] = arr[1];
ptr = arr_ptrs;
Язык C в принципе может сделать это для вас автоматически, если вы попытаетесь привести двумерный массив к указателю на указатель, но это нарушит ожидание программиста, что приведение не имеет побочных эффектов, таких как выделение памяти.
В Java, для сравнения, двумерный массив всегда является массивом указателей на массивы, так что массив
char arr[][] = { {'a', 'b'}, {'c', 'd'} };
размещается в памяти как три отдельных выделения, впроизвольный порядок и не обязательно соседний,
arr -> arr[0]
arr[1]
arr[0] -> arr[0][0]
arr[0][1]
arr[1] -> arr[1][0]
arr[1][1]
Вы сразу заметите, что для этого требуется больше памяткичем эквивалентный массив C, и медленнее оценивать во время выполнения.С другой стороны, он позволяет разным длинам строк массива.