| Итоговая таблица для тех кто не хочет много читать | |||
| Результат | Ошибка компиляции | False | True | 
| Языки | C++ Pascal FORTRAN-95 Java C# Go Rust Haskel | C Lisp Python Lua Ruby | JavaScript PHP Perl | 
Компилятор C выдаёт предупреждение, компилятор C++ ошибку которая превращается в предупреждение если указать флаг -fpermissive.
Под катом для каждого из языков приведена строчка кода, вызвавшая тот или иной результат, с небольшим комментарием.
Бонусом — функции вывода на консоль для этих языков.
Ошибка компиляции
Самый простое и неинтересное поведение — это ошибка компиляции, происходит во всех строго типизированных языках.
C++
cout << (2 + 2 == "4") << endl; error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
Если указать флаг -fpermissive то произойдёт сравнение указателя на строку и числа 4 которое скорее всего вернёт 0.
Pascal
writeln((2 + 2) = "4");Fatal: illegal character "'"'" ($22)
Сообщение об ошибке довольно непонятное
writeln(2 + 2 = '4');Error: Incompatible types: got «Char» expected «Int64»
Сообщение об ошибке стало вполне понятным. Спасибо GebekovAS.
FORTRAN-95
Print *, 2 + 2 == "4"Error: Operands of comparison operator '==' at (1) are INTEGER(4)/CHARACTER(1)
Забавно что в этом тексте нет собственно сообщения о том, что сравнение невозможно, просто констатация факта.
Java
System.out.println((2 + 2) == "4");error: incomparable types: int and String
В сообщение об ошибке всё хорошо кроме того, что не указана какая операция вызвала ошибку.
C#
Console.WriteLine((2 + 2) == "4");error CS0019: Operator `==' cannot be applied to operands of type `int' and `string'
Тут всё хорошо.
Go
fmt.Printf(2 + 2 == "4")cannot convert «4» to type int
invalid operation: «4» == 2 + 2 (mismatched types string and int)
А тут еще лучше
Rust
println!("{:?}", 2 + 2 == "4");error: the trait `core::cmp::PartialEq<&str>` is not implemented for the type `_` [E0277]
Логичное, но честно говоря далеко не самое понятное сообщение об ошибке
Haskel
main = putStrLn (show ((2 + 2) == "4"))No instance for (Num Char) arising from a use of `+'
Сперва я не понял сообщение, потом немного подумал и понял. Но стал понимать Haskel еще меньше чем раньше.
Решение от Sirikid если всё таки очень хочется сравнить ideone.com/CJifV3
Результат False
Следующие на очереди языки которые позволяют сравнивать число и строку, при этом возвращая false (или что-то похожее), скорее всего из-за несовпадения типов переменных.
C
printf("%i\n",(2 + 2 == "4"));результат — 0. Сравнение указателя на строку и числа 4 скорее всего вернёт 0. При этом выводится предупреждение, почти такое же как в C++:
warning: comparison between pointer and integer [enabled by default]
Lisp
(write (eq "123" 123))результат — NIL
Python
print (2 + 2 == "4")результат — False
Lua
print(2 + 2 == "4")результат — false
Ruby
puts 2 + 2 == "4";результат — false
1С
2+2=«4»False
Спасибо, ACPrikh. «Адинэснеги встали в ряд гуру C Lisp Python Lua Ruby.»
Результат True
И наконец языки которые вернут true для сравнения.
JavaScript
console.log(2 + 2 == "4");К счастью есть операция строгого сравнения (тройное равенство ===), которая вернёт false
PHP
echo (2 + 2 == "4");Так же, как и в JavaScript есть операция тройное равенство, результатом которой будет FALSE, что при выводе на консоль выглядит как пустая строка (если я что-то путаю поправьте меня).те меня).
Perl
print 2 + 2 == "4";Операции строгого сравнения нет, кроме того для шестнадцатеричной записи (а почему бы и нет)
print 0x2 + 0x2 == "0x4";Perl интерпретирует строку «0x4» как 0 (в отличие от JavaScript и PHP, которые разбирают шестнадцатеричные строки) и вернёт FALSE, при выводе на консоль так же будет пустая строка.
REXX
say 2+2="4"true
Спасибо, impetus. «При дефолтных ключах/настройках, что документировано и для этого языка логично и ожидаемо.»
Tcl
puts [expr { 2 + 2 == "4" }]true
Спасибо Chpock, «every value is a string».
Есть ли еще языки с необычным поведением при сравнении числа со строкой, я пока не знаю.
Для изучения вопроса использовался сайт, используемые версии компиляторов и интерпретаторов соответствуют предоставленным на сайте.
UPDATE
Исправил досадную ошибку с паскалем, спасибо указавшим. И добавил примеры из комментариев.
Комментарии (83)
 - alex_ter04.06.2017 16:00+2- Pascal В паскале вместо двойных кавычек нужно использовать одинарные.
 
 writeln((2 + 2) = «4»);
 
 Fatal: illegal character "'"'" ($22)
 
 Сообщение об ошибке довольно непонятное
 - Mutineer04.06.2017 16:04+14- error: incomparable types: int and String 
 
 В сообщение об ошибке всё хорошо кроме того, что не указана какая операция вызвала ошибку.
 
 
 Как не указано? Incomparable же
 - iSage04.06.2017 16:11+4- error: incomparable types: int and String 
 
 В сообщение об ошибке всё хорошо кроме того, что не указана какая операция вызвала ошибку.
 Очевидно же, что incomparable может возникнуть только в результате compare — т.е. сравнения.
 - impwx04.06.2017 16:47+12- Автор открыл для себя сильную и слабую виды типизации.  - MaM05.06.2017 00:05-13- Автор фигней какой-то помаялся, недавно пациента видел который учиться в Израиле, и думает, что static инициализируется каждый раз при обращении, в подкасте РадиоТ о перформансе чет говорят и то, что надо закидывать железом и писать на питоне норм, программисты дорогое удовольствие и тд и тп Боже как же я стал ненавидеть этих ваших хипстеров программистов заполонивших отрасль. Строгая статическая для них не удобная, все знают, что динамическая лучше и конечно же 2+2 = «4» должно быть true, а язык Си — синтаксис которого учиться за две недели для них сложен и вообще. Я даже щупая перегруженный swift везде явно типы писал ибо удобно и почему нет. Я раньше не понимал, тех кто гонит программистов-гребцов на галеры, ан нет теперь понимаю, пуст давятся в этих ваших офисах, у меня все пусть ненависть наполнит ваши глаза.  - vlreshet05.06.2017 10:02+2- а язык Си — синтаксис которого учиться за две недели О боже! Автор книги «С++ за 21 день» — это вы? - impwx05.06.2017 10:32+4- Справедливости ради, именно синтаксис нового языка можно выучить и быстрее, если до этого уже на чем-то писал. А вот научиться программировать с нуля — согласен, невозможно.  - vlreshet05.06.2017 10:45-1- Да в си и с синтаксисом беда. Он очень перегружен, куча разных конструкций, операторов, разных смыслов в зависимости от конструкции. Если под «выучить» имеется ввиду уровень универской лабораторной — тогда да. А если имеется в виду адекватный уровень — то я не уверен что для си хватит 2 недели.  - OnYourLips05.06.2017 10:53+6- Вы ничего не путаете? Синтаксис языка C примитивен по сравнению с другими популярными языками. 
 Какие конструкции и операторы вы имеете ввиду?- Eldhenn05.06.2017 11:05+1- int (*(*(*f3)(int))(double))(float);  - impwx05.06.2017 12:02- Синтаксис - typedefна удивление запутанный, но легко запомнить правило «из центра по спирали».
 
 Кстати. кто-нибудь из знающих людей может объяснить, почему при создании алиаса для массива типа X скобки ставятся около нового типа?
 
 - typedef int arr[]; // так положено typedef int[] arr; // но почему не так?- mayorovp05.06.2017 13:12+3- Потому что синтаксис typedef повторяет синтаксис объявления переменных. 
 - Тут надо спрашивать почему объявления переменных сделаны настолько нелогично. Видимо, когда-то давно считалось, что массив — это не отдельный тип данных, а модификатор переменной.  - impwx05.06.2017 13:47- Спасибо! Теперь всё встало на свои места. Легко поверить, что во времена первого C, когда повсеместно использовалась адресная арифметика, было так: тип задает размер указателя, а сколько там элементов подряд идет — один или несколько — это уже модификатор переменной. 
 
 
  - iCpu06.06.2017 09:47- Справедливости ради, 90% задач не требуют таких монструозных конструкций, да и C99 позволяет писать вместо этой вакхвнвлии 
 
 А это старый стандарт.- typedef int (*f1)(float); typedef f1 (*f2)(double); typedef f2 (*f3)(float);
 
  - vlreshet05.06.2017 11:50-2- Разнообразные "*&><^" во всех возможных местах. Или я путаю с С++? Если да — то пардон, посыпаю голову пеплом  - PavelZhigulin05.06.2017 20:30- Самое смешное, что если убрать взятие адреса и разыменование указателя, эти же символы употребляются в тех же самых контекстах, что и в остальных С-подобных языках. 
 
 
 
 
 
 
 
 - Chpock04.06.2017 17:24- tcl — 1 (то бишь true) 
 
 - % puts [expr { 2 + 2 == "4" }]
 1
 %
 
 что логично — «every value is a string»
 - Sirikid04.06.2017 17:44+6- Pascal - Одинарные кавычки fpc, одинарные кавычки gpc, двойные кавычки gpc. 
 Рано вы остановились, вообще у распространенных компиляторов Паскаля свои диалекты и немного некорректно на основании ошибки одного компилятора делать выводы о всех.
 - Go - Вместо - fmt.Printfдолжен быть- fmt.Print, или вы забыли форматную строку.
 - Rust - Скорее всего вы использовали старую версию компилятора, в последнем stable нормальное сообщение. А если явно указать тип, ошибка будет уже другая. 
 - Haskell - Это магия числовых литералов :^) Если явно указать их тип, будет уже конкретная ошибка несоответствия типов оператора сравнения. 
 - Lisp - А какой это Lisp? В Common Lisp, например, - eqэто самое строгое равенство. - Sirikid04.06.2017 19:35- Придумал более интересный инстанс https://ideone.com/CJifV3  - igormich8805.06.2017 19:54- То есть можно добавить новую операцию сложения, которая внутри себя преобразует результат обычного сложения в строку — здорово! Надо будет почитать про Haskell, хотя бы для общего развития. 
 А компиляторы/интерпретаторы я использовал какие были на сайте — ставить на рабочий комп такой зоопарк как то не очень хочется.
 
  - sun-sapient05.06.2017 19:33- Lisp: 
 не важно какой лисп, разные типы
 - N> (class-of "123") #<BUILT-IN-CLASS SB-KERNEL:SIMPLE-CHARACTER-STRING> N> (class-of 123) #<BUILT-IN-CLASS COMMON-LISP:FIXNUM>
 
 - MrSelfDestruct04.06.2017 18:23-12- Для python сравниваются разные типы данных 
 - print (2 + 2 == 4) 
 В Вашем случае будет False, поскольку правая часть выражения является str, а левая int.
 
 Правильней вот так:
 - print (2 + 2 == 4)- splav_asv04.06.2017 19:17+4- Так в этом и суть(сравнение результата арифметического выражения со строковым представлением правильного результата), или я что-то не понимаю? 
 
 - gro04.06.2017 20:13- >Perl интерпретирует строку «0x4» как 0 
 
 Вообще любую строку или только строковые литералы? - cynovg04.06.2017 21:14- Если отключить warnings, то при попытке использовать сложение (а не конкатенацию) Perl попытается привести строку к числу. Для этого он начнет анализировать строку слева на право и отбросит всё, начиная с первого символа, отличного от числа. Всё, что останется — будет интерпретировано, как число. 
 
 Если включить режим предупреждений, то будет выведено предупреждение: Argument «0x4» isn't numeric in addition (+).
 
 - cynovg04.06.2017 21:25- Perl приводить 0x2 к строке (что при использовании прагмы warnings вернет предупреждение) по тому, что происходит сравнение с строкой, если производить сравнение с числом, всё будет тип-топ. На пример: 
 
 print 0x2 + 0x2 == 0x4;
 
 вернет 1
 - impetus04.06.2017 22:10- язык REXX (regina) — true оба варианта: и 2+2='4' и - 2+2="4" (при дефолтных ключах/настройках ), что документировано и для этого языка логично и ожидаемо.
 - oleg_gf04.06.2017 22:50-7- В общем, самый осмысленный результат выдают JS и PHP.  - denis-isaev05.06.2017 01:17+4- Антропный коммент кодера на js и php? :)  - oleg_gf06.06.2017 09:03-2- Если бы я ещё был кодером… )) 
 Если просто здраво рассудить с точки зрения пользователя, то сравнение 2 + 2 = «4» должно выдавать либо истину, либо ложь, в зависимости от точности запроса. С этой точки зрения самый осмысленный результат выдают JS и PHP. - cynovg06.06.2017 09:22+1- Не пользователя, а программиста, наверное. А вот с моей точки зрения — тут явная ошибка, на которую как минимум надо выводить предупреждение. Иначе, это ещё один способ отстрелить себе ногу. 
 
 Ниже, кстати, приводится поведение того же JS в более сложных случаях, и это поведение — следствие той «магии», которая пытается исправить ошибку.
 
 
 
 - lagranzh05.06.2017 02:12+3- В C и C++ теоретически может вернуться тру, если строка "4" случайно окажется расположеной по адресу 4. 
 я так думаю.- Eldhenn05.06.2017 11:25- 0x00F Ever change the value of 4? 
 0x010… Unintentionally?
 0x011… In a language other than Fortran?
  - LmTinyToon05.06.2017 18:23- Зависит от окружения, если не ошибаюсь, windows например резервирует начальные адреса для отладки, поэтому под ней строка никогда не окажется по адресу 4  - Tujh06.06.2017 09:37- Не для отладки, туда загружаются системные библиотеки если я не путаю и память помечается защищённой от записи.  - LmTinyToon06.06.2017 11:57+2- Мои знания могут быть устаревшими (читал книгу по Рихтеру — на тот момент Windows 2000/98). В тех версиях windows (думаю на данный момент ничего не изменилось) — существовал раздел адресного пространства для выявления нулевых указателей (занимал первые 0xFFFF байт для 32/64 битных версий). Любая попытка чтения/записи из данного раздела запрещена.  - Tujh06.06.2017 12:47- Да, я забыл про первые 64к и нет, ваши знания не устарели и всё так и осталось :) 
 
 
 
 
 - Error102405.06.2017 02:35- Pascal 
 
 writeln((2 + 2) = «4»);
 
 Fatal: illegal character "'"'" ($22)
 
 Сообщение об ошибке довольно непонятное
 
 Глупая статья
 - keydon205.06.2017 04:12- Статья больше интересна по теме «как компилятор\интерпретатор пишут об ошибках». 
 По многим сообщениям действительно не сразу понимаешь что именно нужно исправить.
 Это серьезное упущение, учитывая, что обычно их допускают новички и для них интерпретация ошибок в новых языках дело затратное и негативно сказывается на обучении, да и опытным программистам приходится часто их видеть.
 - shushu05.06.2017 08:05+1- В перл сравнения со строками надо делать оператором eq 
 - print 2+2 eq "4" ? "TRUE" : "FALSE"; # > TRUE
  - igormich8805.06.2017 19:44- Так ведь результат в данном случае будет тот же, что строку приводить к числу, что число к строке.  - cynovg05.06.2017 21:55- Не совсем. В первом случае строка приводится к числу, во втором — число к строке. Приведу пример, для наглядности: 
 
 - #!/usr/bin/env perl use warnings; print 2 + 2 == "4a"; print 2 + 2 eq "4a";
 В первом сравнении будет выведена предупреждение «Argument „4a“ isn't numeric in numeric eq (==)», но результат сравнения будет положительным (почему — см. мой комментарий выше). Во-втором случае будет просто false и всё.
 
 
 - chemistmail05.06.2017 08:21-7- Да уж. Исследование. 
 
 haskell:
 ? print $ show $ 2 + 2 == 4
 «True»
 
 А в вашем примере вы сравнили 2+2 :: Int
 c «4» :: String
 И получили ошибку сравнения теплого с мягким. О чем компилятор честно и сказал. - Sirikid05.06.2017 08:42+1- Во-первых, суть была именно в этом. Во-вторых, компилятор сказал совершенно о другом. 
 
 - RogueShy05.06.2017 10:18- Powershell: 
 - echo (2+2 -eq "4") 
 True- То же для одинарных кавычек. 
 Однако,
 - "4" -is [string] 
 True- А если 
 - [int]$a = 2 + 2 
 [char]$b = "4"
 echo ($a -eq $b)
 False- mayorovp05.06.2017 10:39-1- При чем тут вообще char? Тут же во всех языках со строками сравнивают, а не с символами.  - Tujh05.06.2017 12:44-2- В С/С++ нет понятия строк в синтаксисе языка, они слишком низкоуровневые для этого. В «С» есть только массив чаров, а в «С++» шаблон стандартной библиотеки являющийся контейнером для некоторого типа данных (чары или «широкие чары») и позволяющий выполнять операции конкатенации и т.п. над последовательностью данных, но это не встроенный тип и более того, можно написать свои собственные «строки» работающие с utf8, к примеру. - mayorovp05.06.2017 13:14- В Си/С++ строкой является любой массив байт или указатель на первый элемент такого массива.  - Tujh05.06.2017 13:48-1- То есть int string[10] — тоже строка? Массив байт же. 
 И это… как бы процитируйте пункт стандарта языка «С» который бы подтвердил Ваши слова.
 Я могу процитировать учебник по Си, если Вам интересно:
 - Язык Си не поддерживает отдельный строковый тип данных, но он позволяет определить строки двумя различными способами. В первом используется массив символов, а во втором — указатель на первый символ массива. 
 
 Определение char а[10]; указывает компилятору на необходимость резервирования места для максимум 10 символов. Константа а содержит адрес ячейки памяти, в которой помещено значение первого из десяти объектов типа char.- mayorovp05.06.2017 13:49- Ну оговорился я. Символов, конечно же, не байт. Хоть это и "почти синонимы". 
 
 
  - Mutineer05.06.2017 19:26+1- Ну как сказать 
 
 — указатель на массив из двух char- "4"
 
 — одиночный char- '4'
 Типа может и нет, а разница при записи литерала есть
 
 
 
 - hamnsk05.06.2017 11:57- Интересное исследование, сравнить результат сложения двух чисел со строкой. А сразу как бы не понятно что для языков со строгой типизацией результат будет либо ошибкой либо false. 
 - GebekovAS05.06.2017 13:22+1- Pascal: 
 - begin 
 writeln(2+2='4');
 end.
 Результат:
 source.pas(6,17) Error: Incompatible types: got «Char» expected «Int64»
 source.pas(8) Fatal: There were 1 errors compiling module, stopping
 
 p.s. для протокола - GebekovAS05.06.2017 13:29- Кстати, попробовал на стареньком компиляторе TBPascal, вернул: 
 Error: no common type between integer and string ("=", line 4) - GebekovAS05.06.2017 21:20- Первый мой коммент был верен для Free Pascal версии 3.0.0 и выше версии, а вот скрин результата Borland Pascal v7 (классика): 
  
 p.s. теперь думаю ответ можно считать исчерпывающим=) спасибо автору за nostalgie
 
 
 - vladbarcelo05.06.2017 16:41- 2 + 2 = «4» это ещё шуточки для JS: 
 - > '5' - 3 2
 - Отнимаем int от строки, получаем int. А если наоборот? 
 - > '5' + 3 '53'
 - А если наоборот, то получаем конкатенацию в строку. Неплохо, правда? Ну хорошо, а если от строки отнять строку? 
 - > '5' - '4' 1
 - … получаем int! 
 - Ещё немного магии. Строка плюс плюс строка: 
 - > '5' + + '5' '55'
 - Конкатенация, вроде всё понятно. Ну-ка ещё раз: 
 - > 'foo' + + 'foo' 'fooNaN'
 - О как! 
 Ещё JS забавно воспринимает знаки математических действий:
 - > '5' + - '2' '5-2' > '5' + - + - - + - - + + - + - + - + - - - '2' '52'
 - И, напоследок, немного javascript-алгебры: 
 - > var x = 3; > '5' + x - x 50 > '5' - x + x 5
 - teh end. 
 Нет, это всё, разумеется, элементарно объясняется- но понять новичку что такое weak typing + implicit conversions, и почему вообще это всё так работает — это целое удивительное путешествие, ЕВПОЧЯ.  - saw-friendship05.06.2017 19:07-2- Вот совсем неудивительно что в языках со строгой типизацией это не канает. Интереснее было бы, еслиб вы сравнили это выражение без заключения четверки в кавычки. 
 В каких языках 2 + 2 == 4 будет ложным?
  - elnardu05.06.2017 19:31-1- В паскале строки заключаются в ' '. 
 - writeln((2 + 2) = '4');
 
 Error: Incompatible types: got «Char» expected «Int64»
  - chv05.06.2017 19:31-2- Вообще-то в Паскале строки заключаеются в одинарные кавычки. И сообщение об ошибке там вполне понятное. 
 
 
           
 







Shtucer
Вполне понятное. Заключите строку в одинарные кавычки.