А вот хуй.
Это C а не C++. Может какой-нибудь C98 поэтому ему поебать на подобные приведения.
Hellsy в заголовке поста приплёл плюсы, так что тестируем на CXX, а не CC.
%s проморгал, да, правда первой ошибки это не убирает.
%s проморгал, да, правда первой ошибки это не убирает.
И да, там %s, а не %d
Clang'ом десятым попробуй.
Сейчас бы сравнивать динамическую типизацию и статическую. По факту тут все типы показаны. Число, символ в кодировке ascii, и адрес строки, который был увеличен на 1 и поэтому строка стала на 1 символ меньше.
Господи... Почему я это знаю...
Господи... Почему я это знаю...
Ну кстати всё понятно.
Да, вы не понимаете.
Да, это другое.
Да, это другое.
На будущее, если хочешь покидаться говном в плюсовиков, спроси их, почему ни gcc ни clang не видят очевидного UB/segfault вот в таком коде.
В чем здесь твоя проблема? Без дефиниций этих функций, тут нет никакой ошибки.
Передавая данные в чёрный ящик внешней ф-ции, надо быть уверенным, что передаёшь что-то валидное. Проверить некорректность своих данных можно не зная содержимого этих чёрных ящиков.
Если код приводит к ub/sf это косяк программиста, а не компилятора. Ещё скажи что все jmp инструкции должны проверять "а нормальный ли там дальше код".
Стандарт языка способствует UB. А компиляторы слепы, либо делают вид, что не видят.
Я не хочу покидаться говном в плюсовиков, я хочу покидаться говном в людей, которые полагают, что если кто-то не знает и не понимает как работает C/C++ - то мол сам виноват, а если кто-то не знает и не понимает как работает JS, то это потому что JS плох.
Хотя в обоих случаях нужно понимать, что ты делаешь и зачем.
Хотя в обоих случаях нужно понимать, что ты делаешь и зачем.
Как раз такая хуета очень плоха если человеку со стороны нужно подредактировать пару параметров. А в результате имеем дикий рандом ибо обывателю это цветок-цветок, фрукт-фрукт, сисьска-сисьска. И в итоге получается блядский рандомайзер на ровном месте.
JS плох, потому что интерпретатор и слабая динамическая типизация. Нет, разумеется, в этом есть свои плюсы, аж целый один, можно быстрее наговнокодить что-то. Но с ростом сложности проекта, растет вероятность отстрела ног в различных местах, которые можно будет найти только в рантайме. Чем более строгую систему типов имеет язык, тем бОльшую часть ошибок можно сделать не ошибками времени выполнения, а ошибками компиляции. Нет, конечно, можно делать тесты, но зачем человеку делать работу, которую может выполнить компилятор (тесты нужны, но лучше их написать на что-то более осмысленное, да и тесты тоже могут что-то упустить).
Разумеется, Си неидеален. Его система типов куда строже, чем у JS, но все равно очень слабая и позволяет (особенно без -Wall -Werror) отстреливать себе ноги в куче различных мест, например через неявный каст void* куда угодно.
C++ в этом плане уже лучше, особенно если писать, так скзаать, на Modern C++, с активным использованием статики и прочего компил-тайма. Но и C++ неидеален.
Дальше можно взять какой-нибудь Rust. Его система типов (во многом вдохновленная ФП-языками) еще более строгая и выразительная, и позволяет еще больше ошибок ловить. И не только ошибки по работе с памятью, чем знаменит Rust, но, к примеру, проверить что в паттерн-матчинге (некий аналог switch-case) по enum были обработаны ВСЕ возможные ветви, или что переданный в функцию параметр ТОЧНО не какой-нибудь null (Option в Rust).
Мало Rust? Боюсь, тут надо расчехлять тяжелую артиллерию. Haskell.
Мало и его? Что ж, тут уже полный пиздец, берите Irdis. Это хаскеллеподобный язык с зависимыми типами, который позволяет строить формальные доказательства корректности программ на этапе компиляции. Например, формально верифицировать, что если у вас массив и некое заранее неизвестное число, была сделана проверка, что это число не выходит за границы массива. Но это уже почти эзотерика.
Рекомендую хорошую статью на хабре: Парсите, а не валидируйте на тему того, как строгие системы типов помогут нам писать более безопасные и надежные проги.
А возвращаясь к JS, скажу, что JS заслужанно хейтят как старое легаси-говно, имеющее полтора миллиона способа отстрелить себе конечности и программировать на нем можно не благодаря, а вопреки.
Радует одно, что в индустрии есть тренд на движение в этом направлении. Тот же TypeScript (кстати, это не C# для веба, там довольно интересная система типов, как я понимаю, хоть от говно-наследия JS он не избавился), и Rust, и даже для Python, который остается динамически типизируемым, есть аннотации типов, которые могут быть использованы линтерами для проверки, что ваш код не слишком говно.
Случай из жизни: я каждый день на работе использую питон с тайп аннотациями и линтер, и заявляю, что это уже не раз спасало мою ногу и помогало в написании кода, когда прямо в IDE видишь, что пишешь хуйню.
Разумеется, Си неидеален. Его система типов куда строже, чем у JS, но все равно очень слабая и позволяет (особенно без -Wall -Werror) отстреливать себе ноги в куче различных мест, например через неявный каст void* куда угодно.
C++ в этом плане уже лучше, особенно если писать, так скзаать, на Modern C++, с активным использованием статики и прочего компил-тайма. Но и C++ неидеален.
Дальше можно взять какой-нибудь Rust. Его система типов (во многом вдохновленная ФП-языками) еще более строгая и выразительная, и позволяет еще больше ошибок ловить. И не только ошибки по работе с памятью, чем знаменит Rust, но, к примеру, проверить что в паттерн-матчинге (некий аналог switch-case) по enum были обработаны ВСЕ возможные ветви, или что переданный в функцию параметр ТОЧНО не какой-нибудь null (Option в Rust).
Мало Rust? Боюсь, тут надо расчехлять тяжелую артиллерию. Haskell.
Мало и его? Что ж, тут уже полный пиздец, берите Irdis. Это хаскеллеподобный язык с зависимыми типами, который позволяет строить формальные доказательства корректности программ на этапе компиляции. Например, формально верифицировать, что если у вас массив и некое заранее неизвестное число, была сделана проверка, что это число не выходит за границы массива. Но это уже почти эзотерика.
Рекомендую хорошую статью на хабре: Парсите, а не валидируйте на тему того, как строгие системы типов помогут нам писать более безопасные и надежные проги.
А возвращаясь к JS, скажу, что JS заслужанно хейтят как старое легаси-говно, имеющее полтора миллиона способа отстрелить себе конечности и программировать на нем можно не благодаря, а вопреки.
Радует одно, что в индустрии есть тренд на движение в этом направлении. Тот же TypeScript (кстати, это не C# для веба, там довольно интересная система типов, как я понимаю, хоть от говно-наследия JS он не избавился), и Rust, и даже для Python, который остается динамически типизируемым, есть аннотации типов, которые могут быть использованы линтерами для проверки, что ваш код не слишком говно.
Случай из жизни: я каждый день на работе использую питон с тайп аннотациями и линтер, и заявляю, что это уже не раз спасало мою ногу и помогало в написании кода, когда прямо в IDE видишь, что пишешь хуйню.
P.S.
> Хотя в обоих случаях нужно понимать, что ты делаешь и зачем.
Вот я долгое время любил C++ и писал на нем. И вроде все нормально, кроме того, что постоянно надо думать, что ты делаешь и зачем, постоянно жопа горит от того, а правильно ли ты делаешь тут, а правильно ли там, а вдруг, щас РРАААЗ - и полетели ноги, или неоптимальное копирование, и прочее говно. Вот, вроде бы, не сложно, но стопицот тыщ миллиардов вариантов в этих ваших плюсах. На Си, кстати, такого нет, ИМХО. Куча способов отстрелить себе ногу указателями, но зато Си простой как топор.
А потом я попробовал поучить Rust ради любопытства. Там свои заебы, но, оказалось, можно писать без страха.
> Хотя в обоих случаях нужно понимать, что ты делаешь и зачем.
Вот я долгое время любил C++ и писал на нем. И вроде все нормально, кроме того, что постоянно надо думать, что ты делаешь и зачем, постоянно жопа горит от того, а правильно ли ты делаешь тут, а правильно ли там, а вдруг, щас РРАААЗ - и полетели ноги, или неоптимальное копирование, и прочее говно. Вот, вроде бы, не сложно, но стопицот тыщ миллиардов вариантов в этих ваших плюсах. На Си, кстати, такого нет, ИМХО. Куча способов отстрелить себе ногу указателями, но зато Си простой как топор.
А потом я попробовал поучить Rust ради любопытства. Там свои заебы, но, оказалось, можно писать без страха.
Да, для типизации есть TS, работающий поверх JS на уровне предкомпиляции.
И его система типизации не то, что строже - она лучше всего, что есть в C/C++/C#/Java, не говоря уже о популярных интерпретаторах типа Perl/PHP/Python.
В рантайме типизация простенькая (в C/C++ она, впрочем, вообще отсутствует), однако ее можно сделать строгой сторонними библиотеками через декораторы. Да и эксепшины тоже можно добавить:
Например так:
Object.prototype.toString = function() { alert('Куда, блядь?!'); return "Не делай так, мудила!"; };
let a = { };
document.write('a' + a);
А для полной анальной огороженности и паранойи придуман Redux, хотя он больше подходит любителям какого-нибудь React-a.
В общем, за многие годы работы с JS я сталкивался с неочевидным способом выстрелить себе в ногу наверное всего пару раз. Потому что ну нет там никакого особенного легаси.
При этом существует множество способов выстрелить себе в ногу, не связанных с типизацией. Почему-то никто не ноет о thread-safety и race condition, о полноценной поддержке регулярных выражений с бэктрейсом, о возможности выбора стратегии работы GC, о сложностях отладки (привет от C, с его прекрасным seg. fault - ебись с этим как хочешь), и т.д., и т.п. Складывается ощущение, что единственная проблема, которая мучает людей - это как сложить, сука, Object и Array.
И его система типизации не то, что строже - она лучше всего, что есть в C/C++/C#/Java, не говоря уже о популярных интерпретаторах типа Perl/PHP/Python.
В рантайме типизация простенькая (в C/C++ она, впрочем, вообще отсутствует), однако ее можно сделать строгой сторонними библиотеками через декораторы. Да и эксепшины тоже можно добавить:
Например так:
Object.prototype.toString = function() { alert('Куда, блядь?!'); return "Не делай так, мудила!"; };
let a = { };
document.write('a' + a);
А для полной анальной огороженности и паранойи придуман Redux, хотя он больше подходит любителям какого-нибудь React-a.
В общем, за многие годы работы с JS я сталкивался с неочевидным способом выстрелить себе в ногу наверное всего пару раз. Потому что ну нет там никакого особенного легаси.
При этом существует множество способов выстрелить себе в ногу, не связанных с типизацией. Почему-то никто не ноет о thread-safety и race condition, о полноценной поддержке регулярных выражений с бэктрейсом, о возможности выбора стратегии работы GC, о сложностях отладки (привет от C, с его прекрасным seg. fault - ебись с этим как хочешь), и т.д., и т.п. Складывается ощущение, что единственная проблема, которая мучает людей - это как сложить, сука, Object и Array.
Что есть типизация в рантайме? Рефлексия? Ассерты? Если какие-то рантайм проверки, то толку от них, смысл в том, чтоб отловить все статически на этапе коипиляции (ну да, TS).
Про перечисленные вами штуки я не в курсе, потому что на жс никогда толком не писал. А строгая типизация - это добро и приносит счастье. В том же питоновском проекте на работе до того, как ввели типы и линтер типов, местами была боль, потому что передавалось хуй знает что хуй знает куда. Потом оно фиксилось, но это надо ещё найти... А сколько раз раз мне IDE говорила "куда, блять, передал nullable объект, мудила, туда его нельзя" просто не сосчитать. Да и автокомплит лучше работает. Сплошные плюсы.
Про перечисленные вами штуки я не в курсе, потому что на жс никогда толком не писал. А строгая типизация - это добро и приносит счастье. В том же питоновском проекте на работе до того, как ввели типы и линтер типов, местами была боль, потому что передавалось хуй знает что хуй знает куда. Потом оно фиксилось, но это надо ещё найти... А сколько раз раз мне IDE говорила "куда, блять, передал nullable объект, мудила, туда его нельзя" просто не сосчитать. Да и автокомплит лучше работает. Сплошные плюсы.
ЗЫ. Если запускать скомпилированную программу (на том же C/C++) под дебаггером, то в случае получения какого-то сегфолта она стопорится и можно посмотреть всякие переменные, память, стектрейс.
Увы, на продакшине подход с деббагером не очень-то работает.
Основной толк от рантайм-проверок лежит в области валидации моделей. Это когда приходит неебовый JSON(или XML, или ответ от БД, или еще что-то), который надо натянуть на имеющийся под него класс, убедившись, что в полученном объекте есть все нужные поля и их значения соответствуют типам.
В JS для аналогичных функций есть библиотека ClassValidator (и не только она), которая работает... ну как-то вот так:
export class Post {
@Length(10, 20)
title: string;
@Contains("hello")
text: string;
@IsInt()
@Min(0)
@Max(10)
rating: number;
@IsDate()
createDate: Date;
}
validate(post).then(errors => ...
Это не то, чтобы прям рантайм-валидация - ее надо каждый раз запускать (можно устроить через геттеры/сеттеры, впрочем), но все-таки это способ проверить модель, получить список ошибок и что-то с этим знанием дальше делать, а не просто забить хуй, как это делают почему-то 9 из 10 разработчиков.
Основной толк от рантайм-проверок лежит в области валидации моделей. Это когда приходит неебовый JSON(или XML, или ответ от БД, или еще что-то), который надо натянуть на имеющийся под него класс, убедившись, что в полученном объекте есть все нужные поля и их значения соответствуют типам.
В JS для аналогичных функций есть библиотека ClassValidator (и не только она), которая работает... ну как-то вот так:
export class Post {
@Length(10, 20)
title: string;
@Contains("hello")
text: string;
@IsInt()
@Min(0)
@Max(10)
rating: number;
@IsDate()
createDate: Date;
}
validate(post).then(errors => ...
Это не то, чтобы прям рантайм-валидация - ее надо каждый раз запускать (можно устроить через геттеры/сеттеры, впрочем), но все-таки это способ проверить модель, получить список ошибок и что-то с этим знанием дальше делать, а не просто забить хуй, как это делают почему-то 9 из 10 разработчиков.
Окей-окей, я понял. Не, это тру. Валидировать данные на входе, парсить их в типизированную структуру, а дальше пользоваться со спокойной совестью.
Подозреваю, что потому что анализ идет на этапе компиляции, а не линковки, поэтому анализ может быть произведен только в рамках одной единицы трансляции.
ЗЫ. А что, компиляторы достаточно умны, чтобы понять, что тут что-то не так, если бы функции были бы не extern? Я сейчас проверил, вроде не ругается.
ЗЫ. А что, компиляторы достаточно умны, чтобы понять, что тут что-то не так, если бы функции были бы не extern? Я сейчас проверил, вроде не ругается.
extern просто приведён как пример случая, когда недоиннициализированные данные скармливаются куда-то, где мы не можем контролировать дальнейшее поведение в случае забитых мусором указателей, например.
1. int + int, все ясно.
2. int + char. А char - в С неявно приводится к int. Что уебанство. Поэтому к 11 прибавился ASCII код символа "1".
3. строковый литерал + int. Строка - указатель const char*. Операция "+" для указателей определена и это "увеличить указатель на sizeof". Поэтому там был напечатан второй символ строки. А это не уебанство, это адресная арифметика, и на ней живет 2/3 Си и половина С++.
2. int + char. А char - в С неявно приводится к int. Что уебанство. Поэтому к 11 прибавился ASCII код символа "1".
3. строковый литерал + int. Строка - указатель const char*. Операция "+" для указателей определена и это "увеличить указатель на sizeof". Поэтому там был напечатан второй символ строки. А это не уебанство, это адресная арифметика, и на ней живет 2/3 Си и половина С++.
Чисто для интереса, в какой же сфере вы работаете, что вам нужно знание C и C++?
Разработка по для встраиваемых индустриальных систем под линукс.
в то время питон
Справедливости ради, и в JS, и в C, корень проблемы один - неявное приведение типов.
Чтобы написать коммент, необходимо залогиниться