Написать пост

Не баг, а фича: странное поведение языков программирования

Аватар Евгений Туренко

Иногда при написании кода можно заметить, что что-то работает не так, как вы ожидали. Дело не в ошибках в коде, а в языках...

Обложка поста Не баг, а фича: странное поведение языков программирования

Иногда язык программирования ведёт себя не так, как этого ожидает программист. Перевели для вас подборку забавных фич разных языков.

C/C++

  • В языке C можно индексировать массивы следующим образом:
			a[10]
		

И это очень распространённый способ.
Однако существует и другая, менее известная реализация:

			10[a]
		

Код означает то же самое, что и пример выше.

Прим. перев. Такой эффект возникает из-за того, что в языке C операция обращения по индексу a[b] — это синтаксический сахар для *(a + b), что, конечно, эквивалентно *(b + a) и в свою очередь b[a].

  • Триграф в C и C++:
			int main() {
   printf("LOL??!");
}
		

На экран будет выведено LOL| без ??!, так как эти три знака формируют триграф |.

Прим. перев. Триграфы были удалены в C++17.

  • В языке C метки case оператора switch могут находиться внутри вложенных блоков кода. Ниже приведён пример функции memcpy с использованием этого метода.
			void duff_memcpy( char* to, char* from, size_t count ) {
    size_t n = (count+7)/8;
    switch( count%8 ) {
    case 0: do{ *to++ = *from++;
    case 7:     *to++ = *from++;
    case 6:     *to++ = *from++;
    case 5:     *to++ = *from++;
    case 4:     *to++ = *from++;
    case 3:     *to++ = *from++;
    case 2:     *to++ = *from++;
    case 1:     *to++ = *from++;
            }while(--n>0);
    }
}
		

Прим. перев. Этот приём известен как «устройство Даффа».

  • Для каких странностей могут использоваться шаблоны в C++?

Лучше всего это продемонстрировано в «Многомерных аналоговых Литералах», которые используют шаблоны для вычисления площади нарисованных символами форм. Код ниже действителен для прямоугольника ниже.

			#include"analogliterals.hpp"
using namespace analog_literals::symbols;

          unsigned int c = ( o-----o
                             |     !
                             !     !
                             !     !
                             o-----o ).area;
		

Другой пример с кубом:

			assert( ( o-------------o
            |L             \
            | L             \
            |  L             \
            |   o-------------o
            |   !             !
            !   !             !
            o   |             !
             L  |             !
              L |             !
               L|             !
                o-------------o ).volume == ( o-------------o
                                              |             !
                                              !             !
                                              !             !
                                              o-------------o ).area * int(I-------------I) );
		

Java

  • В Java следующий код:
			int[] numbers() {
  return null;
}
		

Может быть записан таким образом:

			int numbers() [] {
  return null;
}
		
  • Странное поведение при упаковке целых значений в Java:
			public class Scratch
{
    public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;
        System.out.println(a == b);

        Integer c = 100, d = 100;
        System.out.println(c == d);
    }
}
		

После запуска кода в первом случае будет выведено false, а во втором — true.

Примечание Объяснение этой особенности языка хорошо описано на Stack Overflow.

PHP

  • Как PHP обрабатывает числовые значения в строках:
			"01a4" != "001a4"
		

Язык PHP не любит строки. Он ищет оправдания для того, чтобы рассматривать введённые в строки значения в виде чисел. Измените немного шестнадцатеричные символы, и PHP внезапно решит, что они уже не относятся к строкам — они становятся числами в научном понимании (PHP не важно, что вы использовали кавычки). Значения выше эквивалентны, так как нули перед другими цифрами игнорируются. Чтобы подкрепить это утверждение, давайте глянем на другой пример:

			"01e4" == "001e4"
		

Для PHP эти значения равны, и это задокументированное явление.

JavaScript

  • Странности при сложении и вычитании в JavaScript:
			'5' + 3 // ='53'
		

Но при этом операция ниже выполняется согласно ожиданиям:

			'5' - 3 // =2
		
  • Таблица «истины» в JavaScript:
			''        ==   '0'           // false
0         ==   ''            // true
0         ==   '0'           // true
false     ==   'false'       // false
false     ==   '0'           // true
false     ==   undefined     // false
false     ==   null          // false
null      ==   undefined     // true
" \t\r\n" ==   0             // true
		
  • И ещё немного JS напоследок:
Не баг, а фича: странное поведение языков программирования 1

Примечание Ещё у нас есть интересная статья о скрытых шутках и возможностях в Python.

А для вас что было самым странным и необычным в языках программирования, с которыми вы работаете?

Следите за новыми постами
Следите за новыми постами по любимым темам
25К открытий25К показов