В C, когда вы использовали имя массива в выражении (включая передачу его функции), если он не является операндом оператора адреса (&
) или оператора sizeof
, он распаковывает на указатель на его первый элемент.
То есть, в большинстве контекстов array
эквивалентно &array[0]
как для типа, так и для значения.
] В вашем примере my_array
имеет тип char[100]
, который распадается на char*
, когда вы передаете его в printf.
&my_array
имеет тип char (*)[100]
(указатель на массив из 100 char
]). Поскольку это операнд &
, это один из случаев, когда my_array
не сразу разлагается на указатель на его первый элемент.
Указатель на массив имеет одинаковое значение адреса как указатель на первый элемент массива, поскольку объект массива является просто непрерывной последовательностью его элементов, но указатель на массив имеет другой тип для указателя на элемент этого массива. Это важно, когда вы выполняете арифметику указателя на двух типах указателя.
pointer_to_array
имеет тип char *
- инициализируется для указания на первый элемент массива, поскольку это то, что my_array
распадается на в выражении инициализатора - и &pointer_to_array
имеет тип char **
(указатель на указатель на char
).
Из них: my_array
(после распада на char*
), &my_array
и pointer_to_array
все указывают непосредственно на массив или первый элемент массива и поэтому имеют одинаковое значение адреса.
Я не знаком с log4net или журналом. DebugFormat (...).
, Но стоимость входа находится действительно в двух областях.
первым является регистрирующийся вызов, и вторым является фактическое сохранение информации о журнале.
защита помогает уменьшить регистрирующийся вызов до минимума, когда вход не на самом деле необходим. Это имеет тенденцию быть очень быстрым, так как это немного больше, чем вызов метода и сравнение двух скаляров.
Однако, когда Вы не используете защиту, стоимость может стать ценой создания фактических аргументов входа.
, Например, в log4j, это было общей идиомой:
log.debug("Runtime error. Order #" + order.getOrderNo() + " is not posted.");
Здесь, стоимость является фактической оценкой строкового выражения, делающего сообщение. Это вызвано тем, что независимо от регистрирующегося уровня, то выражение и получившая строка создаются. Вообразите, было ли вместо этого у Вас что-то как:
log.debug("Something wrong with this list: " + longListOfData);
, Который мог создать большую и дорогую строковую переменную, которая, если бы уровень журнала не был установлен для ОТЛАДКИ, была бы просто потрачена впустую.
защита:
if (log.isDebug()) {
log.debug(...);
}
Устраняют ту проблему, так как вызов isDebug является дешевым, особенно по сравнению с фактическим созданием аргумента.
В моем коде, я записал обертку для входа, и я могу создать журналы как это:
log.debug("Runtime error. Order # {0} is not posted.", order.getOrderNo());
Это - хороший компромисс. Это полагается на Java varargs, и мой код проверяет регистрирующийся уровень, и затем форматирует сообщение соответственно. Это почти с такой скоростью, как защита, но намного более чистый для записи.
Теперь, журнал. DebugFormat может сделать подобную вещь, которую я не знаю.
вдобавок к этому, конечно, фактическая стоимость входа (на экран, в файл, в сокет, и т.д.). Но это - просто стоимость, которую необходимо принять. Моя лучшая практика для этого, когда практично, должна направить фактические сообщения журнала очереди, которую тогда пожинают и производят к надлежащему каналу с помощью отдельного потока. Это, по крайней мере, помогает сохранить выходящую строку с основным вычислением, но это имеет расходы и собственную сложность.
log4net FAQ имеет ответ на это , хотя не к уровню детализации Вы ищете.
, Таким образом: используйте те защитные пункты.