Вы можете зарегистрировать свой собственный обработчик ошибок в PHP. Например, сброс всех ошибок в файл может помочь вам в этих неясных случаях. Обратите внимание, что ваша функция будет вызвана, независимо от того, какой ваш текущий error_reporting установлен. Очень простой пример:
function dump_error_to_file($errno, $errstr) {
file_put_contents('/tmp/php-errors', date('Y-m-d H:i:s - ') . $errstr, FILE_APPEND);
}
set_error_handler('dump_error_to_file');
Давайте начнем с обсуждения правового кода. То, что вы написали (предполагая символ перед каждой декларацией), не будет компилироваться по нескольким причинам: у вас слишком много инициализаторов (шесть символов для arr [0], а его размер равен 5) и, конечно, char ** p не имеет типа, совместимого с char arr [2] [5]. Исправляя эти проблемы, получаем:
char arr[2][6] = { "hello", "hai" };
char (*p)[6] = arr;
Без какого-либо двойного указателя. Если вы хотите получить доступ к одиночным символам в приведенном выше примере, вам нужно указать элемент, из которого они пришли:
char* pc = *arr;
будет работать, если вы хотите получить доступ к символам из первого элемента в обр.
C ++ не имеет двухмерных массивов. Первое определение выше определяет массив [2] или массив [6] символа. Массив implicite для преобразования указателя приводит к указателю на массив [6] символа. После этого, конечно, нет никакого массива для преобразования указателя, потому что у вас больше нет массива.
Я попытаюсь нарисовать, как
int array[10][6];
и
int **array2 = malloc(10 * sizeof *array2);
for (int i = 0; i < 10; ++i)
array2[i] = malloc(6 * sizeof **array2);
выглядят в памяти и как они отличаются (и что они не могут
array
выглядит так:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | | | ..............| | | (10*6 elements of type int)
- - - - - - - - - - - - - - - - - - - - - -
< first row >< second row> ...
array2
выглядит так:
_ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | (10 elements of type int *)
- - - - - - - - - -
| | .... | _ _ _ _ _ _
| | \-->| | | | | | | (6 elements of type int)
| | - - - - - -
| |
| | _ _ _ _ _ _
| \ -->| | | | | | | (6 elements of type int)
| - - - - - -
|
|
| _ _ _ _ _ _
\ -->| | | | | | | (6 elements of type int)
- - - - - -
Когда вы говорите array[x][y]
, он переводится в *(((int *)array)+x*6+y)
. Хотя, когда вы говорите array2[x][y]
, он переводится в *(*(array2+x)+y)
. То есть статический 2d-массив является фактически массивом 1d с строками, помещенными в одну строку. Индекс рассчитывается по формуле row * number_of_columns_in_one_row + column
.
Динамический массив 2d, однако является всего лишь 1d массивом указателей. Затем каждый указатель динамически выделяется для указания на другой 1-й массив. По правде говоря, этот указатель может быть любым. Может быть NULL
или указывать на одну переменную или указывать на другой массив. И каждый из этих указателей устанавливается индивидуально, поэтому они могут иметь разные натуры.
Если вам нужно передать указатель array
где-то, вы не можете направить его на int **
(представьте, что бы int
значения ячеек array
интерпретируются как указатели и разыменованные -> Bam! Ошибка сегментации!). Однако вы можете думать о array
как о 1d массиве int [6]
s; это 1-й массив элементов с типом int [6]
. Чтобы записать это, вы говорите
int (*p)[6] = array;
Создание массива указателей для каждой строки для получения объекта, который «выглядит», как многомерный массив переменной размерности , является дорогостоящим выбором дизайна для синтаксического сахара . Не делайте этого.
Правильный способ создания многомерного массива переменного размера - это что-то вроде:
if (w > SIZE_MAX/sizeof *m/h) goto error;
m = malloc(w * h * sizeof *m);
if (!m) goto error;
...
m[y*w+x] = foo;
Если вы хотите, чтобы он выглядел красиво, чтобы вы могли напишите m[y][x]
, вы должны использовать другой язык, возможно, C ++.
int (*foo)[cols] = malloc(sizeof *foo * rows)
позволяет использовать знакомый синтаксис foo[i][j]
;
– Christoph
17 December 2010 в 17:57