C: Сравнение с NULL

Если у вас запущена служба SMTP, вы можете outfile в каталог drop. Если у вас большой объем, вы можете получить дубликаты имен файлов, но есть способы избежать этого.

В противном случае вам нужно будет создать UDF.

Вот пример решения триггера:

CREATE TRIGGER test.autosendfromdrop BEFORE INSERT ON test.emaildrop
FOR EACH ROW BEGIN
      /* START THE WRITING OF THE EMAIL FILE HERE*/      
      SELECT  concat("To: ",NEW.To),
              concat("From: ",NEW.From),
              concat("Subject: ",NEW.Subject),
              NEW.Body
          INTO OUTFILE 
                   "C:\\inetpub\\mailroot\\pickup\\mail.txt" 
              FIELDS TERMINATED by '\r\n' ESCAPED BY '';            
END;

Чтобы разметка тела сообщения вам понадобится что-то вроде это ...

CREATE FUNCTION `HTMLBody`(Msg varchar(8192)) 
    RETURNS varchar(17408) CHARSET latin1 DETERMINISTIC
BEGIN
  declare tmpMsg varchar(17408);
  set tmpMsg = cast(concat(
      'Date: ',date_format(NOW(),'%e %b %Y %H:%i:%S -0600'),'\r\n',
      'MIME-Version: 1.0','\r\n',
      'Content-Type: multipart/alternative;','\r\n',
      ' boundary=\"----=_NextPart_000_0000_01CA4B3F.8C263EE0\"','\r\n',
      'Content-Class: urn:content-classes:message','\r\n',
      'Importance: normal','\r\n',
      'Priority: normal','\r\n','','\r\n','','\r\n',
      'This is a multi-part message in MIME format.','\r\n','','\r\n',
      '------=_NextPart_000_0000_01CA4B3F.8C263EE0','\r\n',
      'Content-Type: text/plain;','\r\n',
      '  charset=\"iso-8859-1\"','\r\n',
      'Content-Transfer-Encoding: 7bit','\r\n','','\r\n','','\r\n',
      Msg,
      '\r\n','','\r\n','','\r\n',
      '------=_NextPart_000_0000_01CA4B3F.8C263EE0','\r\n',
      'Content-Type: text/html','\r\n',
      'Content-Transfer-Encoding: 7bit','\r\n','','\r\n',
      Msg,
      '\r\n','------=_NextPart_000_0000_01CA4B3F.8C263EE0--'
      ) as char);
  RETURN tmpMsg;
END ;
23
задан Ande TURNER 24 July 2014 в 09:42
поделиться

11 ответов

Мне нравится второе, другим людям нравится первое.

На самом деле, я предпочитаю третий вид первому:

if (NULL == ptr) {
   ...
}

Потому что тогда я:

  • не смогу пропустить и просто наберу один «=»
  • не пропустит «== NULL» и примет его за противоположное, если условие длинное (несколько строк)

Функционально они эквивалентны.

Даже если указатель NULL не равен «0» (все нулевые биты), if (!ptr) сравнивается с указателем NULL.

Следующее неверно. Это все еще здесь, потому что есть много комментариев, ссылающихся на это: Однако не сравнивайте указатель с буквальным нулем. Это будет работать почти везде, но поведение IIRC неопределено.

17
ответ дан Tony 24 July 2014 в 09:42
поделиться

Я предпочитаю явный стиль (первая версия). Это делает очевидным, что задействован указатель, а не целое число или что-то еще, но это просто вопрос стиля.

С точки зрения производительности, это не должно иметь никакого значения.

33
ответ дан Laserallan 24 July 2014 в 09:42
поделиться

Эквивалентная. Так сказано в языковом стандарте. И люди имеют чертовски религиозные предпочтения!

31
ответ дан Norman Ramsey 24 July 2014 в 09:42
поделиться

Часто полезно предположить, что авторы компиляторов обладают как минимум минимальным интеллектом. Ваш компилятор не написан сотрясенными утятами. Он написан людьми с многолетним опытом программирования и годами изучения теории компиляторов. Это не означает, что ваш компилятор совершенен и всегда знает лучше, но это действительно означает, что он вполне способен обрабатывать тривиальные автоматические оптимизации.

Если две формы эквивалентны, то почему бы компилятору просто не перевести одну в другую, чтобы убедиться, что обе они одинаково эффективны?

Если if (pointer[i] == NULL) медленнее, чем if (!pointer[i]), не будет компилятор просто меняет его на вторую, более эффективную форму?

Так что нет, если они эквивалентны, они одинаково эффективны.

Что касается первой части вопроса, да, они эквивалентны. В стандарте языка где-то это явно указано где-то - указатель оценивается как true, если он не равен NULL, и false, если он равен NULL, поэтому оба значения в точности совпадают.

19
ответ дан jalf 24 July 2014 в 09:42
поделиться

Почти наверняка нет разницы в производительности. Я предпочитаю неявный стиль второго.

9
ответ дан Barry Kelly 24 July 2014 в 09:42
поделиться

NULL должен быть объявлен в одном из стандартных заголовочных файлов следующим образом:

#define NULL ((void*)0)

Так или иначе, вы сравниваете ноль, и компилятор должен оптимизировать оба одинаковых способа. Каждый процессор имеет некоторую «оптимизацию» или код операции для сравнения с нулем.

3
ответ дан Mark Rushakoff 24 July 2014 в 09:42
поделиться

Ранняя оптимизация плохая. Микрооптимизация также плоха, если вы не пытаетесь выжать из процессора все последние биты Гц, нет никакого смысла делать это. Как уже показали люди, компилятор в любом случае оптимизирует большую часть вашего кода.

Лучше сделать ваш код максимально лаконичным и читабельным. Если это более читабельно

if (!ptr)

, чем это

if (NULL==ptr)

, используйте его. Пока все, кто будет читать ваш код, соглашаются.

Лично я использую полностью определенное значение (NULL == ptr), поэтому ясно, что я проверяю. Может быть, больше, чтобы напечатать, но я могу легко прочитать это. Я думаю, что! PTR будет легко пропустить! если читать быстро.

1
ответ дан shimpossible 24 July 2014 в 09:42
поделиться

Это действительно зависит от компилятора. Я был бы удивлен, если бы большинство современных компиляторов Си не генерировали практически идентичный код для конкретного сценария, который вы описываете.

Получите ваш компилятор для генерации списка сборки для каждого из этих сценариев, и вы можете ответить на свой вопрос (для вашего конкретного компилятора:)).

И даже если они различаются , разница в производительности, вероятно, будет несущественной в практических приложениях.

0
ответ дан 24 July 2014 в 09:42
поделиться

Включите оптимизацию компилятора, и они в основном одинаковы

проверили это на gcc 4.3.3.

int main (int argc, char** argv) {
   char c = getchar();
   int x = (c == 'x');
   if(x == NULL)
      putchar('y');
   return 0;
}

и

int main (int argc, char** argv) {
   char c = getchar();
   int x = (c == 'x');
   if(!x)
      putchar('y');
   return 0;
}


gcc -O -o test1 test1.c
gcc -O -o test2 test2.c


diff test1 test2

не дали результатов: )

0
ответ дан Charles Ma 24 July 2014 в 09:42
поделиться

Я выполнил дамп сборки и обнаружил разницу между двумя версиями:

@@ -11,8 +11,7 @@
pushl %ecx
subl $20, %esp
movzbl -9(%ebp), %eax
- movsbl %al,%eax
- testl %eax, %eax
+ testb %al, %al

Похоже, что последний генерирует одну инструкцию, а первый - две, но это довольно ненаучно.

Это gcc, без оптимизации:

test1.c:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{ 
  char *pointer[5];

if(pointer[0] == NULL) {
  exit(1);
}

exit(0);

}

test2.c: Измените pointer[0] == NULL на !pointer[0]

gcc -s test1.c, gcc -s test2.c, diff -u test1.s test2.s

-2
ответ дан ctennis 24 July 2014 в 09:42
поделиться
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{   
  char pointer[5];  
  /* This is insense you are comparing a pointer to a value */   
  if(pointer[0] == NULL) {     
    exit(1);
  } 
  ...
}

=>           ...    
  movzbl    9(%ebp), %eax  # your code compares a 1 byte value to a signed 4 bytes one 
  movsbl    %al,%eax        # Will result in sign extension...
  testl  %eax, %eax      
              ...

Осторожно, gcc должен был выдать предупреждение, если не скомпилировать регистр с флагом -Wall на Хотя вы всегда должны компилировать оптимизированный код gcc. Кстати, перед переменной используйте ключевое слово volatile, чтобы gcc не игнорировал ее ...

Всегда упоминайте свою версию сборки компилятора:)

-2
ответ дан ZeroCool 24 July 2014 в 09:42
поделиться
Другие вопросы по тегам:

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