K&R: массив символьных указателей

Да, у каждого приложения свой формат даты.

И даже каждое приложение может иметь более одного сеанса, каждый с различным форматом сеанса, указанным для DATE и TIMESTAMP.

SQL Developer имеет настройки уровня приложения, определенные на странице «Предпочтения», «База данных», «NLS». Вот как будут отображаться DATE, если вы не введете ALTER SESSION SET ... в своем рабочем листе SQL.

Или, если вы всегда хотите определенный формат независимо от этого параметра, встроите его в свой запрос.

select to_char(sysdate, 'DAY') today from dual;

enter image description here

5
задан Deduplicator 23 January 2015 в 11:20
поделиться

4 ответа

Выбранный ответ Адама Розенфилда неверен. Ответ coobird тоже. По этой причине я проголосовал за оба ответа.

Интерпретация Адама Марковица * lineptr ++ верна, но он не отвечает на главный вопрос, является ли это допустимым кодом C99. Только Tom Future делает; к сожалению, он не объясняет * lineptr ++ . Я присвоил им по очку.

Итак, для краткости, lineptr - это переменная, которой можно управлять как указателем. Таким образом, увеличение указателя является допустимым.

lineptr - указатель на последовательность указателей на последовательности символов. Другими словами, это указатель на первую строку массива строк. Согласно коду мы можем предположить, что строки являются последовательностями символов с завершающим нулем ('\ 0'). nlines - количество строк в массиве.

Выражение теста while: nlines-> 0 . nlines - - пост-декремент (поскольку - находится справа от переменной). Таким образом, он выполняется после теста и независимо от результата теста, так что в любом случае.

Итак, если значение nlines , указанное в качестве аргумента, было 0 , тест выполняется первым и возвращает false ; инструкции в цикле не выполняются. Обратите внимание, поскольку nlines все равно уменьшается, значение nlines после цикла while будет -1 .

If nlines == 1 , тест вернет true и nlines будут уменьшены; инструкции в цикле будут выполнены один раз. Обратите внимание, что пока эти инструкции выполняются, значение nlines равно 0 . Когда тест выполняется снова, мы возвращаемся к случаю, когда nlines == 0 .

В инструкции printf используется выражение * lineptr ++ . Это пост-инкремент указателя ( ++ справа от переменной). Это означает, что выражение вычисляется первым, а приращение выполняется после его использования. Таким образом, при первом выполнении printf получает копию первого элемента массива строк, который является указателем на первый символ строки. lineptr увеличивается только после этого. В следующий раз, когда printf должен быть выполнен, lineptr указывает на второй элемент и будет перемещен к третьему, когда вторая строка будет напечатана. Это имеет смысл, потому что мы, очевидно, хотим напечатать первую строку. Если бы Адам Розенфилд был прав, первая строка была бы пропущена, и в конце мы попытались бы вывести строку после последней, что, очевидно, плохо.

Таким образом, инструкция printf является краткой формой двух следующих инструкций

printf("%s\n", *lineptr);
++lineptr; // or lineptr++, which is equivalent but not as good. lineptr += 1; is ok too.

. Обратите внимание, как практическое правило, когда пре- и пост-инкремент эквивалентны по своему действию, предварительный -increment предпочтительнее по соображениям производительности. Компиляторы позаботятся о том, чтобы переключить его за вас. Ну, большую часть времени. По возможности лучше обращаться к предоператорам самостоятельно, чтобы они использовались всегда.

4
ответ дан 18 December 2019 в 07:10
поделиться

lineptr на самом деле не массив; это указатель на указатель. Обратите внимание, что оператор постинкремента ++ имеет более высокий приоритет, чем оператор разыменования * , поэтому в lineptr ++ происходит следующее:

  1. lineptr получает увеличивается, чтобы указать на следующий элемент в массиве
  2. Результатом lineptr ++ является старое значение lineptr , а именно указатель на текущий элемент в массиве
  3. * lineptr ++ разыменован, поэтому это значение текущего элемента в массиве

Таким образом,

6
ответ дан 18 December 2019 в 07:10
поделиться

Продолжайте читать! В самом низу стр. 99

В качестве формальных параметров в определении функции

  char s [];

и

  char * s;

эквивалентны; мы предпочитаем последнее, потому что в нем более четко указано, что параметр является указателем.

Т.е. вы никогда не можете передать массив (который не является переменной) функции. Если вы объявляете функцию, которая выглядит так, как будто она принимает массив, она действительно принимает указатель (который является переменной). Это имеет смысл. Было бы странно, если бы аргумент функции не был переменной - он может иметь другое значение каждый раз, когда вы вызываете функцию, поэтому он точно не является константой!

7
ответ дан 18 December 2019 в 07:10
поделиться

Было бы проще представить * lineptr ++ следующим образом:

*(lineptr++)

Здесь указатель на массив char * s равен перемещаемся к следующему элементу массива, то есть из lineptr [0] , мы переходим к lineptr [1] . (Приращение указателя происходит после разыменования из-за постфиксного приращения указателя.)

Таким образом, в основном происходит следующее:

  1. lineptr [0] (типа char * ) извлекается путем обращения.
  2. Указатель увеличивается на следующий элемент массива. (Постфиксным приращением указателя lineptr .)
  3. Теперь указатель указывает на lineptr [1] , повторите процесс, начиная с шага 1.
5
ответ дан 18 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: