Разница между Thread и runnable. Если мы создаем Thread с использованием класса Thread, тогда количество потоков равно количеству созданного нами объекта. Если мы создаем поток, реализуя интерфейс runnable, мы можем использовать один объект для создания нескольких потоков. Один объект разделяется несколькими Thread.So он будет потреблять меньше памяти
. Поэтому в зависимости от требования, если наш данные не являются сенситивными. Таким образом, он может быть разделен между несколькими Thread, которые мы можем использовать интерфейс Runnable.
Вопрос, который вы задаете, - это действительно два вопроса, а не один. Большинство ответов до сих пор пытались охватить всю вещь с помощью общего одеяла «это ответ K & amp; R style», в то время как на самом деле лишь малая его часть имеет какое-либо отношение к тому, что известно как стиль K & amp; R (если вы не видите весь язык C как «K & amp; R-стиль» так или иначе:)
Первая часть - странный синтаксис, используемый в определении функции
int func(p, p2)
void *p;
int p2; /* <- optional in C89/90, but not in C99 */
{
return 0;
}
Это фактически определение функции K & amp; R-стиля. Другой ответ на это довольно хорошо. И на самом деле этого мало. Синтаксис устарел, но полностью поддерживается даже в C99 (за исключением правила «no implicit int» в C99, что означает, что на C99 вы не можете опустить объявление p2
).
Второй часть имеет мало общего с K & amp; R-style. Я обращаюсь к тому факту, что функция может вызываться с «замененными» аргументами, т. Е. В таком вызове не происходит проверки типа параметра. Это очень мало связано с определением K & amp; R-style per se, но оно имеет все, что связано с тем, что ваша функция не имеет прототипа. Вы видите, что в C, когда вы объявляете такую функцию
int foo();
, она фактически объявляет функцию foo
, которая принимает неуказанное количество параметров неизвестного типа . Вы можете назвать его как
foo(2, 3);
и как
j = foo(p, -3, "hello world");
ans и так далее (вы получаете идею);
Только вызов с правильными аргументами будет «работать» (что означает, что другие производят неопределенное поведение), но это полностью зависит от вас, чтобы обеспечить его правильность. Компилятор не обязан диагностировать неправильные, даже если он каким-то образом знает правильные типы параметров и их общее число.
На самом деле это поведение является языка C. Однако опасный, но особенный. Это позволяет вам сделать что-то подобное
void foo(int i);
void bar(char *a, double b);
void baz(void);
int main()
{
void (*fn[])() = { foo, bar, baz };
fn[0](5);
fn[1]("abc", 1.0);
fn[2]();
}
i.e. смешивать разные типы функций в «полиморфном» массиве без каких-либо типов (типы вариационной функции здесь не могут быть использованы). Опять же, присущие опасности этой техники совершенно очевидны (я не помню, чтобы когда-либо ее использовали, но я могу представить, где это может быть полезно), но это C в конце концов.
Наконец, бит, который связывает вторая часть ответа на первый. Когда вы выполняете определение функции K & amp; R-стиля, оно не вводит прототип функции. Что касается типа функции, ваше определение func
объявляет func
как
int func();
i.e. ни типы, ни общее количество параметров не объявлены. В своем оригинальном посте вы говорите: «... кажется, это то, сколько параметров он использует ...». Формально это не так! После вашего двухпараметрического определения K & amp; R-style func
вы все еще можете вызвать func
как
func(1, 2, 3, 4, "Hi!");
, и в нем не будет никаких ограничений. (Как правило, качественный компилятор даст вам предупреждение).
Кроме того, иногда упускается из виду факт, что
int f()
{
return 0;
}
также является определением функции K & amp; R-стиля, которое не вводит прототип. Чтобы сделать его «современным», вам нужно будет поместить явный void
в список параметров
int f(void)
{
return 0;
}
. Наконец, вопреки распространенному мнению, как определения функций K & amp; R-стиля, Прототипные объявления функций полностью поддерживаются в C99. Первый был устаревшим с C89 / 90, если я правильно помню. C99 требует, чтобы функция была объявлена до первого использования, но декларация не требуется для прототипа. Путаница, по-видимому, проистекает из популярного терминологического смешения: многие люди называют любое объявление функции «прототипом», а на самом деле «объявление функции» - это не то же самое, что «прототип».
Это более старый стиль деклараций функций. См. Эту ссылку.
https://stackoverflow.com/questions/22500/what-are-the-major-differences-between-ansi-c-and-kr-c текст ссылки
Это довольно старый синтаксис K & amp; R C (предварительные даты ANSI / ISO C). В настоящее время вы больше не должны его использовать (поскольку вы уже заметили его главный недостаток: компилятор не будет проверять типы аргументов для вас). Тип аргумента по умолчанию по умолчанию соответствует int
в вашем примере.
В то время этот синтаксис использовался, иногда можно было найти такие функции, как
foo(p, q)
{
return q + p;
}
, который фактически был действительным как типы для foo
, p
и q
по умолчанию int
.
Это реликвия, когда у C не было прототипов для функций. Тогда, как мне кажется, предполагается, что функции возвращаются int
, и все его аргументы считались int
.
Вам не удалось выполнить проверку параметров функции на текущем языке C. И вы должны использовать их в C99 (C89 по-прежнему принимает старый синтаксис).
И C99 требует, чтобы функции были объявлены (возможно, без прототипа). Если вы пишете новую функцию с нуля, вам нужно предоставить декларацию ... сделать ее прототипом: вы ничего не теряете и получаете дополнительную проверку от компилятора.
int
было удалено.
– AnT
27 October 2009 в 14:50
Это оригинальный синтаксис K & amp; R до того, как C был стандартизован в 1989 году. C89 представила прототипы функций, заимствованные из C ++, и устарела синтаксис K & amp; R. Нет причин использовать его (и множество причин не) в новом коде.
Это просто старый синтаксис, который предваряет синтаксис «ANSI C», с которым вы, возможно, более знакомы. Обычно это называется « K & amp; R C ».
Компиляторы поддерживают его, чтобы быть полным, и, конечно, иметь возможность обрабатывать старые базы кода.