Pull to refresh
2
0

User

Send message

Я поддержу изначального разработчика (Линуса), потому что у него есть репутация - человека, который создал и держит Линукс.

Если касаться только технической стороны дела, то Linus давно похоронил свою репутацию.

Достаточно взглянуть на это:

Standards and reality

Standards are paper. I use paper to wipe my butt every day. That's how much that paper is worth. Reality is what matters.

и на это:

About testing

"Regression testing"? What's that? If it compiles, it is good; if it boots up, it is perfect.

Ну, а касательно других аспектов, он сам откровенно признался:

Linus Torvalds - "bastard"

I'm a bastard. I have absolutely no clue why people can ever think otherwise. Yet they do. People think I'm a nice guy, and the fact is that I'm a scheming, conniving bastard who doesn't care for any hurt feelings or lost hours of work, if it just results in what I consider to be a better system. And I'm not just saying that. I'm really not a very nice person. I can say "I don't care" with a straight face, and really mean it.

Вот ещё цитата, которая закрывает любую возможность серьёзно относиться к Linus'у:

I'm always right

I'm always right. This time I'm just even more right than usual.

Здесь собрано множество подобных цитат.

Так что, я бы не был столь категоричен относительно репутации.

Хотя бы один.

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

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

Моё мнение - тут надо искать zero cost решение.

Комментарий как раз и является таковым.
Тем более, что подобное решение уже реализовано.

Если в следующем коде:

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

int main(int argc, char **argv) {
	switch (argc) {
	case 4:
		printf("%s", argv[3]);
		/* fallthrough */
	case 3:
		printf("%s", argv[2]);
		// fallthrough
	case 2:
		printf("%s", argv[1]);
	}

	return EXIT_SUCCESS;
}

убрать комментарии, то gcc начнёт выдавать предупреждения this statement may fall through.

А с этими комментариями — не выдаёт.
Совершенно очевидно, что он их читает и понимает.
С заглавной буквы — тоже понимает.

Но зачем усложнять, если в отличии от ситуации знакового переполнения, процессор даже не имеет флага целочисленного переполнения?

Какой процессор?

Я все ещё совершенно не убеждён.

...

Но я на 100% убеждён,

Когда Linus уже повзрослеет и поймёт, что авторитетов не существует?

Среди первоначальных идей — лучше использовать санитайзеры на основе компилятора или возможности языка C для перегрузки операторов без искажения имён.

Комментарии, читаемые компилятором, решают проблему.

соблюдение санкций правительства США про российскому праву незаконно

Насколько я знаю, санкции США незаконны и по международному праву: законны только санкции ООН.

А вот интересно всегда было узнать отношение прогрессивной обществености к касту вида тип(значение).

Если значение — одно, то это — полный эквивалент C-style cast'а, то есть, ничем от него не отличается.

Почитать можно здесь (пункт 2, первый подпункт в Explanation): Explicit type conversion.
А именно:

  • If there is exactly one expression in parentheses, this cast expression is exactly equivalent to the corresponding C-style cast expression.

А C-style cast expression можно использовать, в том числе, и для получения к доступа к static_cast'у с расширениями (пункт 1, подпункт b по той же ссылке).

На сколько я помню, в языке C объявление переменных должно идти в начале функции.

Это — для стандарта C89/C90, начиная же с C99, это — не обязательно.
Стандарту C99 уже 25 лет, так что им уже, наверное, можно начать пользоваться.

Это сишный код, в Си нет ни ссылок, ни nullptr.

Ссылок пока нет, а вот nullptr уже есть в C23, — вот пример.

Используйте Option<T> или Result<T>

Придётся изрядно подождать, пока такое появится в C.

Честно говоря, полезность и целесообразность исследования вызывает вопросы.

А я и не говорю, что это полезно или целесообразно.
Но для ответа на вопрос, достаточно часто или недостаточно часто встречаются случаи, когда расширение файла не соответствует языку его содержимого, чтобы пренебрегать этими случаями, исследование провести необходимо.

Можно и не проводить.
Но тогда на вопрос не ответить.

Высока, но не достаточна. Для написания скриптов на коленке подойдет, но для чего-то серьёзного уже придется поддерживать и чуть-более сложные варианты.

Я не говорю, что серьёзный инструмент не должен учитывать вероятность использования расширения файла не по назначению.

Однако, возвращаясь к начальному моменту, с которого всё и началось: если в проекте, например, в JDK, который, в основном, написан на C++, некий файл, например, VM.c, имеет расширение .c, то надёжность предположения, что там находится код на C, а не на C++, очень высока.

Вот, я о чём.

Достаточно часто чтобы не пренебрегать.

Это — не ответ.
Здесь необходимо взять N проектов и просто проверить.
И убедиться.

Конкретно анализатор без флажков компиляции жить не может, т.к. в них передается информация, без которой не провести полноценное препроцессирование и анализ.

Анализатор — без сомнения.
Хотя бы, чтобы правильно обработать директивы условной трансляции, потому что, к примеру, в командной строке могут передаваться макро-определения, от чего будет зависеть выбор соответствующих частей кода директивами условной трансляции.

Но речь-то была о надёжности определения языка по расширению файла. И эта надёжность очень высока.

Напишем простой код, который при этом не скомпилируется в режиме С++. Положим всё это в main.cpp и соберем плюсовым компилятором в режиме Си (флаг -x c)

И часто такое встречается в реальности?

Всё-таки, в подавляющем большинстве случаев, именно расширение файла — наиболее надёжный признак, на каком языке написано его содержимое.

P.S. Если интересно почему программа вообще собирается на Си, то у нас в документации на диагностику V1107 есть описание (она как раз ловит такие случаи).

Я — в курсе.
И также в курсе, что, начиная с C23, поведение изменено аналогично оному в C++.

Я честно сказал, что сейчас буду гуглить синтаксис указателей на функции, т.к. даже спустя много лет работы эта вещь, почему-то, никак не хочет удержаться у меня в голове.

Здесь как раз тот случай, когда знание некоторых принципов заменяет знание многих фактов.

Новый Gmail аккаунт все еще можно зарегистрировать без тел. номера и он будет работать без требования привязать номер (проверял недавно и не недавно).

До поры, до времени.

Постепенно даже для древних аккаунтов они включают дурачка после проверки запасного e-mail'а или после отправки на запасной e-mail кода и правильного его введения мной: говорят, мол, мы должны убедиться, что это именно вы, поэтому введите номер своего телефона или переходите к процедуре восстановления аккаунта.

Как введение ещё неизвестного им номера телефона позволит им убедиться, что это именно я, а не кто-то другой?

Наглый шантаж в расчёте на несообразительность человека, который из-за этого не заметит подвоха, — шантаж путём блокирования доступа к аккаунту для выманивания номера телефона. Ещё и не всегда работает, возможно, потому, что один и тот же телефон ввожу для нескольких аккаунтов, какая-то глупая ошибка на их стороне возникает.

Или они и считают, что теперь, по прошествии более, чем десятка лет после заведения аккаунтов, я должен завести и несколько номеров телефонов, чтобы сохранить доступ к почте?

Майкрософтовские разрешают создать, но потом через сколько-то месяцев, если не привязал, то меня блокировали, пока не привяжешь.

Здесь — то же самое, просто, возможно, блокировка не так стремительна.
С аккаунтами, для которых уже был указан номер телефона, такого не происходит.

А потом на запасной e-mail приходит издевательское письмо следующего содержания:

Предотвращена попытка входа в аккаунт <такой‑то>

Кто‑то попытался войти в Ваш аккаунт, используя Ваш пароль. Мы
предотвратили попытку, но Вам следует проверить историю действий в
аккаунте.

Так это я и пытался.
А чтобы проверить историю действий, необходимо сначала как-то войти.
Предотвращатели.

С тех пор как они прикрутили обязательное использование OAuth 2.0 для своей почты, все сторонние почтовые клиенты поотваливались.

Thunderbird поддерживает OAuth 2.0.

Только в качестве fallback стратегии.

Я бы не был столь категоричен.

Гораздо лучше получать такую информацию из команд компиляции

Провожу эксперимент:

$ cat > 1.cpp
#include <cstdlib>
#include <iostream>

int main() {
	std::cout << "Yes!" << std::endl; 
	return EXIT_SUCCESS;
}
$ gcc -c 1.cpp
$ 

Интересно, правда?
В строке компиляции, вроде как, должен быть C, а не C++, если судить по имени команды.

Удаётся с'link'овать и исполнить:

$ g++ 1.o
$ ./a.out
Yes!
$ 

Работает.

Хорошо, перекладываю 1.cpp в 1.c и повторяю:

$ cp 1.cpp 1.c
$ gcc -c 1.c
1.c:1:10: fatal error: cstdlib: No such file or directory
    1 | #include <cstdlib>
      |          ^~~~~~~~~
compilation terminated.
$ 

Видно, что сам gcc определяет язык по расширению файла.
А из команд компиляции такую информацию здесь достать нельзя.
Имя команды компиляции тоже не даёт однозначного ответа.

Поэтому нельзя однозначно сказать, что лучше, а что хуже.

Ну если вам важно только расширение,

Это не мне важно, и это был намёк.

то можно посмотреть тут

Код у них в целом плохой, например, приведение в C-шном стиле:

(char*)"com.sun.hotspot.functions.IsClassUnloadingEnabled"

Вместо использования const_cast.
С потенциальной проблемой потом при попытке менять содержимое.

А можно запретить им использовать .h и std:: одновременно, как тут

Расширение .h используется как для C, так и для C++ файлов.

P.S. у них там вперемешку C/C++, поэтому и интересно как с этим справляется анализатор

Очевидно, что анализатор ориентируется по расширению файла.
Как видите, это не мне важно расширение файла.

В JDK используют sizeof(methods)/sizeof(methods[0]) и не жалуются.

https://github.com/openjdk/jdk/blob/master/src/java.base/share/native/libjava/VM.c#L51

А это — ничего, что файл, на который вы ссылаетесь, называется VM.c?
Я имею ввиду расширение файла, — то, что после точки в имени.
Может в этом файле использоваться std::size?

Они ещё и не очень-то владеют языком C.
Используют явное приведение к указателю на void при инициализации структуры JNINativeMethod:

static JNINativeMethod methods[] = {
    {"getNanoTimeAdjustment", "(J)J", (void *)&JVM_GetNanoTimeAdjustment}
};

Структура выглядит так:

typedef struct {
    char *name;
    char *signature;
    void *fnPtr;
} JNINativeMethod;

Последнее поле имеет тип указатель на void.
Поэтому третий инициализатор не требуется приводить явно.
Этот случай, в отличие от приведения в обратную сторону, актуален даже для C++.

Сколько еще таких ошибок в коде JDK найдет ваш анализатор?

Вообще-то, это — не ошибка, особенно в C, где по-другому — никак.

¿А, то есть для стандартных массивов она не делает sizeof/sizeof[]?

Да, верно.

В этом справочнике, который я настоятельно рекомендую, поскольку он, фактически, содержит выжимки из стандартов, а стандарт это — последняя инстанция, для std::size() есть раздел Possible Implementation, в котором есть часть size (3).

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

Вот пример, в котором количество элементов массива a1 задаётся с помощью вызова функции std::size() для массива a0, а количество элементов массива a2 задаётся с помощью вызова функции my::size() для массива a1, которая взята из того самого раздела Possible Implementation, и всё прекрасно компилируется, ни один компилятор даже ни пикнул.

Information

Rating
Does not participate
Registered
Activity