Сильно набрано С?


87

Процитувавши Вікіпедію :

Двома загальновживаними мовами, які підтримують багато видів неявного перетворення, є C та C ++, і іноді стверджують, що це слабо введені мови. Однак інші стверджують, що ці мови встановлюють достатньо обмежень щодо способу змішування операндів різних типів, і ці дві слід розглядати як сильно набрані мови.

Чи є більш чітка відповідь?


188
Для програміста C сильний набір тексту означає сильніше натискання клавіш.
Dan Dyer

2
C знаходиться на слабкій стороні в континуумі набору тексту. Але з обох боків є достатньо предметів, з якими ви можете сперечатися в будь-якому випадку. Поки ви це робите, ви можете також запитати (vi або emacs, netbeans або затемнення тощо)
Черво

4
Стан роботи у Вікіпедії був настільки поганим, що я відчув, що змушений редагувати кілька сторінок Вікіпедії. Можливо, зараз справи йдуть трохи краще. Можливо.
Норман Ремзі

40
Re: Коментар Дана (надати належне там, де це потрібно) Книга Пітера ван дер Ліндена "Програмування експертів на C" містить такий рядок: "На сьогоднішній день багато програмістів на C вважають, що" сильне введення тексту просто означає сильно бити по клавіатурі ".
Александрос Гезерліс,

Дуже гарне запитання !!!
Destructor

Відповіді:


154

"Сильно набраний" та "слабо набраний" - це терміни, які не мають широко узгодженого технічного значення. Терміни, які мають чітко визначене значення, є

  • Динамічно набраний тип означає, що типи приєднуються до значень під час виконання, і спроба змішати значення різних типів може спричинити "помилку під час виконання". Наприклад, якщо в схемі ви намагаєтесь додати його до істинного, написавши (+ 1 #t)це, це призведе до помилки. Ви стикаєтеся з помилкою лише в тому випадку, коли намагаєтесь виконати код, що порушує.

  • Статично набране означає, що типи перевіряються під час компіляції, а програма, яка не має статичного типу, відхиляється компілятором. Наприклад, якщо в ML ви намагаєтесь додати його до true, написавши 1 + trueпрограму, програму буде відхилено із повідомленням про помилку (можливо загадкове). Ви завжди отримуєте помилку, навіть якщо код ніколи не може бути виконаний.

Різні люди віддають перевагу різним системам, зокрема тому, наскільки вони цінують гнучкість і наскільки турбуються про помилки під час виконання.

Іноді "сильно набраний" вживається вільно, щоб означати "статично набраний", а "слабо набраний" використовується неправильно, щоб означати "динамічно набраний". Краще використовувати термін "сильно набраний" полягає в тому, що "ви не можете обійти або зруйнувати систему типів", тоді як "слабо набраний" означає "в системі типів є лазівки". І навпаки, більшість мов із системами статичного типу мають лазівки, тоді як багато мов із системами динамічного типу не мають лазівки.

Жоден із цих термінів жодним чином не пов'язаний з кількістю неявних перетворень, доступних у мові.

Якщо ви хочете поговорити саме про мови програмування, найкраще уникати термінів «сильно введений» та «слабо введений». Я б сказав, що C - це мова, яка набирається статично, але в якій багато лазівки. Одна лазівка ​​полягає в тому, що ви можете вільно перекинути будь-який тип покажчика на будь-який інший тип покажчика. Ви також можете створити лазівку між будь-якими двома типами на ваш вибір, оголосивши об'єднання C, яке складається з двох членів, по одному для кожного з цих типів.

Я писав більше про статичне та динамічне введення тексту на сторінці why-interpreted-langs-are-most-ducktyped-while-compiled-have-strong-typing .


2
Де ви взяли визначення, які ви пропонуєте для сильного / слабкого набору тексту (лазівка)?
Sydius

2
Навіщо вам потрібна "лазівка" в середовищі динамічного набору тексту?
Кріс Конвей

4
@Sydius: Від того, як ми провели більшу частину останніх 20 років у спілкуванні з людьми, які розробляють, будують та аналізують мови програмування та системи друку. Це моя оплачувана робота :-)
Норман Ремзі

@Chris: Я ніколи не бачив динамічно набраної мови з "лазівкою". Типовим використанням лазівки є робота з робочою системою або ОС, наприклад, взяти вихідну адресу та перетворити її на покажчик на добре виховану мовну цінність. Ви можете зробити це в динамічній обстановці, але я не знаю жодної спроби.
Норман Ремсі,

1
@NormanRamsey Я думаю, що Кріс мав на увазі своє запитання:whereas "weakly typed" means "there are loopholes in the type system
Нір Альфасі

23

Важко класифікувати кожну мову на "слабо" або "сильно" набраний текст - це скоріше континуум. Але, порівняно з іншими мовами, C досить сильно набрано. Кожен об’єкт має тип часу компіляції, і компілятор повідомить вас (голосно), якщо ви робите щось із об’єктом, чого його тип не дозволяє. Наприклад, ви не можете викликати функції з неправильними типами параметрів, отримати доступ до структур / членів об'єднання, які не існують, тощо.

Але є кілька недоліків. Однією з основних слабких сторінок є типи передач - вони, по суті, говорять про те, що ви збираєтеся обдурювати типи об'єктів, і компілятор повинен бути тихим (коли це можливо). void*також є ще однією слабкістю - це загальний вказівник на невідомий тип, і коли ви ними користуєтесь, ви повинні бути особливо обережними, щоб поводитися правильно. Компілятор не може статично перевірити більшість застосувань void*. void*також може бути перетворений на вказівник на будь-який тип без приведення (лише на C, а не на C ++), що є ще однією слабкістю.


Приємна відповідь, хоча "typecasts ... і компілятор повинен бути тихим" мене турбує. Подання типу не схоже на вимкнення попередження, воно фактично змінює інтерпретацію значення, на яке посилається.
Високий Джефф,

15
Ви плутаєте "статичний" та "сильний" щодо набору тексту. Ці два поняття не залежать одне від одного.
bendin

1
Денніс Річі (автор C) назвав C "сильно набраним та слабо перевіреним"
TimZaman

11

Література щодо цього не зрозуміла. Я думаю, що сильно набране - це не так / ні, є різний ступінь сильного набору тексту.

Мова програмування має специфікацію того, як вона виконує програми. Іноді незрозуміло, як виконувати певні програми. Наприклад, програми, які намагаються відняти рядок із числа. Або програми, які діляться на нуль. Є кілька способів впоратися з цими станами. Деякі мови мають правила щодо усунення цих помилок (наприклад, вони створюють виняток). Інші мови просто не мають правил для вирішення цих ситуацій. Ці мови, як правило, мають системи типів для запобігання компіляції програм, що призводять до неуточненої поведінки. А також існують мови, які мають невизначену поведінку і не мають системи типу, щоб запобігти цим помилкам під час компіляції (якщо ви пишете програму, яка вражає невизначену поведінку, це може запустити ракети).

Тому:

Мови, які визначають, що відбувається під час виконання в кожному випадку (наприклад, додавання числа до рядка), називаються динамічно набраними. Мови, що перешкоджають виконанню програм з помилками під час компіляції, набираються статично. Мови, які не визначають, що відбувається, а також не мають системи типів для запобігання помилкам, називаються слабко набраними.

Тож Java статично набрана? Так, оскільки система його типів забороняє віднімати рядок із числа. Ні, тому що це дозволяє ділити на нуль. Ви можете запобігти діленню на нуль під час компіляції за допомогою системи типів. Наприклад, створивши тип числа, який не може бути нульовим (наприклад, NonZeroInt), і дозволяє ділити лише на числа, що мають цей тип.

Отже, C сильно набрано чи слабо набрано? C сильно набирається, оскільки система типів забороняє деякі помилки типу. Але він слабо вводиться в інших випадках, коли не визначено, що відбувається (а система типу не захищає вас).


Мені подобається ваше поєднання динамічного та статичного як форм сильних проти слабких. Однак я не впевнений, що розумію вашу думку щодо статично набраних систем, які зупиняють ділення на нуль. Якщо мій статично набраний intодержує значення від аргументів користувача або командного рядка або файлу, компілятор нічого не може зробити, щоб зупинити це як нуль!
Ріккі,

1
Існують системи статичного типу, які запобігають цьому, але більшість мов або слабко, або динамічно "набирається" щодо ділення на нуль, оскільки це невизначена поведінка (C), або вони створюють виняток (Java).
Жуль

11

C вважається слабко набраним, оскільки ви можете перетворити будь-який тип на будь-який інший тип за допомогою приведення, без помилки компілятора. Детальніше про проблему ви можете прочитати тут .


2
тут wikipedia вводить в оману. C сильно набирається, типи є дуже дійсними, і компілятор буде баффувати, якщо ви їх помилитеся, однак, C також надає функції, які ви можете обійти. Порівняйте з такими мовами, як BCPL, які мають лише тип "байт".
gbjbaanb

12
Слабко набраний текст не означає, що мова не має жодних типів, це просто означає, що типи можна неявно примушувати від одного типу до іншого. Порівняйте з Python, сильно набраною мовою, в якій потрібно явно перетворювати типи за допомогою викликів функцій.
mipadi

здатний кинути річ на C також сприяє тому, що вона є слабким типом. ?? У мене є ці сумніви, як назавжди
Сурадж Джейн

8

C набирається сильніше, ніж Javascript, і менш набраний, ніж Ada.

Я б сказав, що це більше потрапляє в сильно набрану сторону континууму. але хтось інший може не погодитися (навіть якщо вони помиляються).

Як це для остаточного?


Це була дещо язикова відповідь. Але ретельно уточнюйте несправедливість.
Michael Burr

1
Javascript сильно набраний. Він просто не набраний статично. Всі перевірки типів відбуваються під час виконання (динамічні, а не статичні), але вони трапляються, і заважають вам пошкодити пам'ять (один із аспектів сильного набору тексту).
bendin

5
Ну, як вказує дуже гарна відповідь Норма Ремсі, "сильно набраний" і "слабко набраний" не є особливо чітко визначеними термінами. Крім того, що стосується того, що Javascript набирається сильно, деякі можуть вважати, що ("4" / ​​"2") як дійсний вираз Javascript може вказувати інакше.
Michael Burr

5

C вважається статично набраним (ви не можете змінити змінну з int на float). Як тільки змінна оголошена, вона закріплюється таким чином.

Але це вважається слабко набраним, оскільки типи можуть бути фліп-флопнутими.

Що таке 0? '\ 0', FALSE, 0,0 тощо.

у багатьох мовах не можна сказати IF (змінна), оскільки умови прийматимуть лише булеві значення з булевих виразів. Вони сильніше набрані. Те саме стосується переходу між символами та цілими числами.

в основному c має два основних простих типи даних, цілі числа та числа з плаваючою комою (хоча різні точні дані). Все інше, логічні значення, перелічення (не прості, але підходять) тощо реалізовані як одне з них. Навіть символи в основному є цілими числами.

Порівняйте з іншими мовами, де є типи рядків, типи переліку, які можна призначити лише визначеним значенням, логічні типи, де можуть використовуватися лише вирази, що генерують логічні значення або true / false.

Але ви можете заперечити, що в порівнянні з Perl C сильно набраний. Тож це один із тих відомих аргументів (vi проти emacs, linux проти windows тощо). C # набирається сильніше, ніж C. В основному ви можете сперечатися в будь-якому випадку. І ваші відповіді, ймовірно, підуть в обидві сторони :) Також у деяких підручниках / веб-сторінках буде сказано, що C - слабко набраний, а хтось - C - сильно набраний. Якщо ви перейдете до wikipedia, у записі C буде написано "частково слабке введення тексту". Я б сказав, що порівняно з Python C слабко набраний. Отже, Python / C #, C, Perl на континуумі.


Поясніть, будь ласка, свої міркування щодо того, що Perl набраний менш сильно, ніж C.
user51568

print "Тестування" + 0 # perl буде робити 0; $ var = "рядок"; $ var = 1; $ var = 123,4; Що це за змінна?
Черво

У C char * test = "тестування"; printf (тестування + 0); все одно буде рядком, просто в C індекс зміниться, якщо замість нуля я використовую число. Це все ще досить слабко, але трохи сильніше, ніж perl. тест char *; тест = 0; тест = 123,4; test = "c"; ... мій компілятор генерує помилки
Черво

помилка говорить про те, що потрібен гіпс. Тим не менше, це трохи сильніше, ніж перевірка типу, ніж Perl, тому на континуумі я повинен сказати, що C набирається сильніше, ніж Perl. Ви все ще можете пройти test = (char *), а потім використовувати 0, 123.4, 'C' тощо. Але це просто помилка.
Cervo

4

Тут є безліч хороших відповідей. Я хочу підкреслити важливий момент від Реального Світу Хаскелла :

Корисно знати, що багато мовних спільнот мають свої власні визначення “сильного типу”. Тим не менше, ми коротко і широко говоритимемо про поняття міцності в типових системах.

(фрагмент)

Феєрверк навколо типів систем сягає корінням із звичайної англійської мови, де люди надають поняття цінності словам «слабкий» та «сильний»: ми зазвичай вважаємо силу кращою, ніж слабкість. Набагато більше програмістів говорять просто англійською, ніж академічний жаргон, і досить часто вчені дійсно кидають цегляні бити на будь-яку систему типу, яка не відповідає їх фантазії. Результатом часто стає те популярне проведення часу в Інтернеті, полум'яна війна.

Отже, подивіться на відповіді про C та C ++, але пам’ятайте, що «сильні» та «слабкі» не відповідають «хорошим» та «поганим».


4

На думку Денніса Річі ( творця C ) та Брайана Кернігана, C не є сильно набраною мовою. Наступні рядки з книги "Мова програмування C", сторінка 3, параграф 5

C не є сильно набраною мовою, але, оскільки вона розвивалася, перевірка її типу була посилена.


3

На мій погляд, C / C ++ сильно набираються. Тип хакерів, що дозволяють конвертувати типи (void *), існує через близькість C до машини. Іншими словами, ви можете викликати команди асемблера з Паскаля і маніпулювати вказівниками, і Паскаль все ще вважається сильно набраною мовою. Ви можете викликати асемблер та виконувані файли C з Java через JNI, але це не робить Java слабко набраним.

C просто має вбудований в нього асемблер із сирими покажчиками тощо.


3

Термін, що вводиться строго введено , не має узгодженого визначення. Тому, якщо ви не визначите, що ви маєте на увазі під терміном «сильно набрано», неможливо відповісти на ваше запитання.

З мого досвіду, терміни "сильно набраний" і "слабко набраний" використовуються виключно тролями, оскільки їх відсутність визначень дозволяє тролям перевизначити їх середній аргумент відповідно до їх порядку денного. За винятком запуску полум'яних вогнів, ці терміни є майже марними.

Можливо, ви також захочете поглянути на: Які ключові аспекти сильно набраної мови? тут на StackOverflow.


3
Я не погоджуюсь. "Сильно набраний" означає, що можна визначити тип даних значення, і дозволяються лише операції, відповідні цьому типу. "Динамічна" та "статична" адреса, коли таке визначення може бути зроблено.
joel.neely

2
Ви робите розуміють іронію намагається спростувати твердження , що там немає узгодженого визначення, ввівши ще одну постанову, НЕ так?
Jörg W Mittag

1
@Jorg: Не намагаючись представити інший; просто вказуючи той, який зазвичай використовується в колах, в яких я рухаюся.
joel.neely

1

Існує континуум із безліччю паралельних шляхів між "слабо введеним" та "сильно введеним", два терміни, які навіть не є чітко визначеними.

C статично набирається, оскільки компілятор знає, що це задекларований тип кожної локальної змінної та члена структури.

Мови, що динамічно набираються, все ще можуть бути сильно набраними, якщо кожен об’єкт має певний тип, але компілятор не може знати цей тип.


0

У чому причина вашого запиту? Причина, по якій я запитую, полягає в тому, що це якась незначна різниця, і саме ваше використання "сильно набраного" може потребувати більш-менш роз'яснень. Я б точно сказав, що Java та інші мови мають жорсткіші обмеження щодо неявних типів розмов.


Здебільшого з цікавістю, але я претендую на позицію C, і хотів би знати на випадок, якщо вони мене про це запитують.
Sydius

Тоді, ймовірно, довша відповідь, яка надає нюанси того, що "сильно набрано", є найкращим підходом, а не просто "так" чи "ні".
BobbyShaftoe

0

Важко дати конкретну відповідь, коли немає конкретного визначення поняття "сильно набрано". Я б сказав, що C сильно набирається, оскільки кожна змінна і кожен вираз має тип, але слабко набирається, тому що дозволяє змінювати типи за допомогою закидів та переосмислювати представлення одного типу як іншого.


Є офіційна деф. для сильно набраних. Там сказано, що sys. є ST, коли гарантується, що немає помилки типу часу роботи. Приклад: ML, Haskell. Це корисно, щоб система опускала теги типів усередині об'єктів, проте застосовувала оператори до правильних типів. Оскільки перед виконанням ми знаємо, що теги в об’єктах не потрібні. Оскільки C має доступ до довільної пам’ятки та вказівник, C не є st
alinsoar

0

Я б сказав, що C набирається так сильно, як диктує ваш компілятор / платформа. Наприклад, якщо ви будуєте на суворій платформі, розіменування покараного покажчика типу, швидше за все, зламається:

void m_free(void **p)
{
        if (*p != NULL) {
                free(*p);
                *p = NULL;
        }
}

....
char *str = strdup("foo");
m_free((void **) &foo);

Тепер, якби ви сказали компілятору пропустити суворе згладжування, це було б проблемою, але не дуже портативною. Отже, у цьому сенсі пересування меж мови можливо, але, мабуть, не найкраща ідея. Це виходить на крок за межі типового кастингу, тобто кастинг int стільки часу і справді показує одну з можливих підводних каменів порожнечі.

Отже, я б сказав, що C в основному набирається строго, але різні його компілятори припускають, що програміст знає найкраще і допускає певну гнучкість. Це насправді залежить від компілятора, дехто не розбереться з цим потенційним ой. Тож у цьому сенсі обраний компілятор справді відіграє певну роль, відповідаючи на запитання. Правильне часто відрізняється від того, що дозволить вам уникнути компілятор.



-1

Не набрано сильно.

Поміркуйте, що наступний прототип функції розповідає вам про типи даних аргументів:

void func (int n, char ch, ...);

Нічого. Тож я припускаю, що тут не застосовується сильний набір тексту.


А? Це говорить вам, що існує int, за яким слідує символ, за яким слід будь-яка кількість аргументів будь-якого типу. Це не "нічого".
Лоуренс Дол

Значок ... нічого не повідомляє про типи переданих аргументів. Це правда, що тип самої функції відомий. Це те, що сказав Software Monkey.
Йоханнес Шауб - літб

Я маю на увазі ці "будь-яку кількість аргументів будь-якого типу". Ланцюг настільки міцний, наскільки найслабша його ланка.
joel.neely

-3

Я б сказав, що це сильно типи, оскільки кожен вираз має тип, який не є функцією його значення; ei це може бути відомо до часу виконання.

OTOH Я не впевнений, що це правильний опис сильно набраного тексту. Єдиною сильнішою претензією, яку я бачу причиною для мови, є гарантія того, що ви не можете підривати систему типів під час виконання за допомогою переосмислення типових типів, об'єднань, викликів на інші мови, покажчиків, мови збірки тощо. Такі мови, як ця існують, але настільки скалічені, що, здається, не представляють особливого інтересу для програмістів поза межами високої впевненості та наукових колах. Як хтось вказував, щоб насправді зробити це правильно, вам починають потрібні такі типи, як nonZeroIntі щось інше . Гидота.


3
Що ні? Моє визначення сильно набраного чи C?
BCS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.