C가 강력하게 입력 되었습니까?


87

Wikipedia 를 인용하려면 :

많은 종류의 암시 적 변환을 지원하는 일반적으로 사용되는 두 가지 언어는 C와 C ++이며, 종종 약한 유형의 언어라고 주장됩니다. 그러나 다른 사람들은 이러한 언어가 서로 다른 유형의 피연산자가 혼합 될 수있는 방법에 대해 충분한 제한을두고 있으며 두 가지가 강력한 유형의 언어로 간주되어야한다고 주장합니다.

더 확실한 답이 있습니까?


188
C 프로그래머에게 강력한 타이핑은 키를 더 세게 누르는 것을 의미합니다.
Dan Dyer

2
C는 타이핑 연속체에서 약한 편입니다. 그러나 어느 쪽이든 논쟁 할 수있는 충분한 항목이 양쪽에 있습니다. 당신이 그것에있는 동안 당신은뿐만 아니라 (VI 또는 이맥스, 넷빈즈 또는 일식 등)을 요청할 수 있습니다
세르

4
Wikipedia의 플레이 상태가 너무 나빠서 여러 Wikipedia 페이지를 편집해야한다고 느꼈습니다. 이제 상황이 조금 더 나아질 수도 있습니다. 아마도.
Norman Ramsey

40
Re : Dan의 의견 (적용 할 시점에 대한 설명) Peter van der Linden의 저서 "Expert C Programming"에는 다음과 같은 내용이 포함되어 있습니다. "오늘날 많은 C 프로그래머들은 '강력한 타이핑은 키보드를 더 세게 두드리는 것을 의미합니다.'라고 믿습니다."
Alexandros Gezerlis 2010

아주 좋은 질문 !!!
소멸자

답변:


154

"강하게 입력"및 "약하게 입력"은 널리 동의 된 기술적 의미가없는 용어입니다. 의미가 잘 정의 된 용어는 다음과 같습니다.

  • 동적 유형 은 유형이 런타임에 값에 첨부됨을 의미하며 다른 유형의 값을 혼합하려고하면 "런타임 유형 오류"가 발생할 수 있습니다. 예를 들어 Scheme에서 (+ 1 #t)이것을 작성하여 true에 추가하려고 하면 오류가 발생합니다. 문제가되는 코드를 실행하려는 경우에만 오류가 발생합니다.

  • 정적으로 형식화 됨은 컴파일 시간에 형식이 확인되고 정적 형식이없는 프로그램은 컴파일러에서 거부됨을 의미합니다. 예를 들어, ML에서를 작성하여 true에 1을 추가하려고 1 + true하면 프로그램이 (아마도 비밀스러운) 오류 메시지와 함께 거부됩니다. 코드가 실행되지 않더라도 항상 오류가 발생합니다.

유연성을 중시하는 정도와 런타임 오류에 대해 걱정하는 정도에 따라 사람마다 다른 시스템을 선호합니다.

때때로 "강력한 유형"은 "정적 유형"을 의미하기 위해 느슨하게 사용되며 "약한 유형"은 "동적 유형"을 의미하는 것으로 잘못 사용됩니다. "강하게 입력 된"이라는 용어의 더 나은 사용은 "유형 시스템을 우회하거나 전복시킬 수 없습니다"라는 것입니다. 반면 "약하게 입력 된"은 "유형 시스템에 허점이 있음"을 의미합니다. 역으로 정적 유형 시스템을 사용하는 대부분의 언어에는 허점이있는 반면 동적 유형 시스템을 사용하는 많은 언어에는 허점이 없습니다.

이러한 용어 중 어느 것도 언어에서 사용할 수있는 암시 적 변환의 수와 어떤 식 으로든 연결되어 있지 않습니다.

프로그래밍 언어에 대해 정확하게 이야기하려면 "강력한 유형"및 "약한 유형"이라는 용어를 피하는 것이 가장 좋습니다. C는 정적으로 입력되지만 많은 허점이있는 언어라고 말할 수 있습니다. 한 가지 허점은 모든 포인터 유형을 다른 포인터 유형으로 자유롭게 캐스팅 할 수 있다는 것입니다. 또한 문제의 각 유형에 대해 하나씩 두 개의 멤버가있는 C 공용체를 선언하여 선택한 두 유형 사이에 허점을 만들 수도 있습니다.

나는 why-interpreted-langs-are-mostly-ducktyped-while-compiled-have-strong-typing 에서 정적 및 동적 타이핑에 대해 더 많이 썼습니다 .


2
강 / 약한 타이핑에 대해 제안한 정의를 어디서 얻었습니까 (허점)?
Sydius

2
동적 타이핑 환경에서 왜 "허점"이 필요합니까?
Chris Conway

4
@Sydius : 지난 20 년 동안 프로그래밍 언어 및 유형 시스템을 설계, 구축 및 분석하는 사람들과 어울리 며 시간을 보냈습니다. 그게 내 유급 직업입니다 :-)
Norman Ramsey

@Chris : '허점'이있는 동적 유형 언어는 본 적이 없습니다. 허점의 일반적인 용도는 런타임 시스템 또는 OS에서 작업하는 것입니다. 예를 들어 원시 주소를 가져와 제대로 작동하는 언어 값에 대한 포인터로 변환합니다. 동적 설정에서이 작업을 수행 할 수 있지만 어떤 시도인지 모르겠습니다.
Norman Ramsey

1
: 나는 크리스는 그의 질문을 언급했다라고 생각 @NormanRamseywhereas "weakly typed" means "there are loopholes in the type system
Nir 씨 Alfasi

23

모든 언어를 '약하게'또는 '강하게'입력 한 것으로 분류하는 것은 어렵습니다. 그러나 다른 언어에 비해 C는 상당히 강력한 유형입니다. 모든 객체에는 컴파일 타임 유형이 있으며 컴파일러는 유형이 허용하지 않는 객체로 무언가를 수행하는 경우 (큰 소리로) 알려줍니다. 예를 들어 잘못된 유형의 매개 변수를 사용하여 함수를 호출하거나 존재하지 않는 구조체 / 유니온 멤버에 액세스하는 등의 작업을 할 수 없습니다.

그러나 몇 가지 약점이 있습니다. 한 가지 주요 약점은 타입 캐스트입니다. 본질적으로 객체 유형을 다루고 컴파일러는 조용해야한다고 말합니다. void*또한 또 다른 약점입니다. 알 수없는 유형에 대한 일반적인 포인터이며이를 사용할 때 올바른 일을하고 있는지 각별히주의해야합니다. 컴파일러는 대부분의 void*. void*캐스트가없는 모든 유형에 대한 포인터로 변환 될 수도 있습니다 (C ++가 아닌 C에서만). 이는 또 다른 약점입니다.


좋은 대답은 "타입 캐스트 ... 그리고 컴파일러는 조용해야한다"는 것이 저를 괴롭 힙니다. 타입 캐스트는 경고를 종료하는 것과는 다르며 실제로 참조되는 값의 해석을 변경합니다.
Tall Jeff

15
타이핑과 관련하여 "정적"과 "강함"을 혼동하고 있습니다. 이 두 개념은 서로 독립적입니다.
bendin

1
C라는 데니스 리치 (C 저자)는 '강력한 형식과 약하게 확인'
TimZaman

11

이것에 대한 문헌은 명확하지 않습니다. 강력한 타이핑은 예 / 아니요가 아니라 다양한 정도의 강력한 타이핑이 있다고 생각합니다.

프로그래밍 언어에는 프로그램을 실행하는 방법에 대한 사양이 있습니다. 때때로 특정 프로그램으로 실행하는 방법이 명확하지 않습니다. 예를 들어, 숫자에서 문자열을 빼려고하는 프로그램이 있습니다. 또는 0으로 나누는 프로그램. 이러한 조건을 처리하는 방법에는 여러 가지가 있습니다. 일부 언어에는 이러한 오류를 처리하기위한 규칙이 있습니다 (예 : 예외 발생). 다른 언어에는 이러한 상황을 처리하는 규칙이 없습니다. 이러한 언어에는 일반적으로 지정되지 않은 동작을 유발하는 프로그램 컴파일을 방지하는 유형 시스템이 있습니다. 또한 지정되지 않은 동작이 있고 컴파일 타임에 이러한 오류를 방지 할 유형 시스템이없는 언어도 있습니다 (지정되지 않은 동작을 수행하는 프로그램을 작성하면 미사일을 발사 할 수 있음).

그래서:

모든 경우 (문자열에 숫자 추가 등)에서 런타임에 발생하는 작업을 지정하는 언어를 동적 유형이라고합니다. 컴파일 타임에 오류가있는 프로그램 실행을 방지하는 언어는 정적으로 입력됩니다. 어떤 일이 발생하는지 지정하지 않고 오류를 방지 할 유형 시스템이없는 언어를 약한 유형이라고합니다.

그렇다면 Java는 정적으로 입력됩니까? 예, 그 유형 시스템은 숫자에서 문자열을 빼는 것을 허용하지 않기 때문입니다. 아니요, 0으로 나눌 수 있기 때문입니다. 타입 시스템을 사용하면 컴파일 타임에 0으로 나누는 것을 방지 할 수 있습니다. 예를 들어 0이 될 수없는 숫자 유형 (예 : NonZeroInt)을 만들고이 유형의 숫자로만 나눌 수 있습니다.

그렇다면 C는 강력하게 입력됩니까 아니면 약하게 입력됩니까? C는 유형 시스템이 일부 유형 오류를 허용하지 않기 때문에 강력하게 입력됩니다. 그러나 어떤 일이 발생하는지 정의되지 않은 다른 경우에는 약하게 입력됩니다 (유형 시스템이 사용자를 보호하지 않음).


나는 강함과 약함의 형태로 동적 및 정적 정렬을 좋아합니다. 그러나 정적으로 형식화 된 시스템이 0으로 나누기를 중지하는 것에 대한 귀하의 요점을 확신하지 못합니다. 내 정적으로 입력 된 int값이 사용자 또는 명령 줄 인수 또는 파일에서 값을 가져 오면 컴파일러가 0이되는 것을 막을 수있는 방법이 없습니다!
Rikki

1
이를 방지하는 정적 유형 시스템이 있지만 대부분의 언어는 정의되지 않은 동작 (C)이거나 예외 (Java)를 던지기 때문에 0으로 나누는 것과 관련하여 약하거나 동적으로 "유형화"됩니다.
Jules

11

C는 컴파일러 오류없이 캐스트를 통해 모든 유형을 다른 유형으로 변환 할 수 있으므로 약한 유형으로 간주됩니다. 여기 에서 문제에 대한 자세한 내용을 읽을 수 있습니다 .


2
wikipedia는 여기에서 오해의 소지가 있습니다. C는 강력한 유형이고 유형은 매우 유효하며 잘못 이해하면 컴파일러에서 경고를 표시하지만 C는이를 우회 할 수있는 기능도 제공합니다. '바이트'유형 만있는 BCPL과 같은 언어와 비교하십시오.
gbjbaanb

12
Weakly typed는 언어에 유형이 없음을 의미하는 것이 아니라 유형이 암시 적으로 한 유형에서 다른 유형으로 강제 변환 될 수 있음을 의미합니다. 함수 호출로 유형을 명시 적으로 변환해야하는 강력한 유형의 언어 인 Python과 비교해보십시오.
mipadi

C에서 사물을 캐스팅 할 수있는 것도 약한 유형이되는 데 기여합니다. ?? 나는 영원히 같은이 의심
SURAJ 자이나교

8

C는 Javascript보다 더 강력하고 Ada보다 덜 강력합니다.

나는 그것이 연속체의 강하게 타이핑 된쪽에 더 많이 떨어진다고 말하고 싶습니다. 그러나 다른 누군가가 동의하지 않을 수 있습니다 (그들이 틀렸더라도).

그것은 어떻게 결정적입니까?


다소 혀를 내미는 대답이었습니다. 그러나 잘못에 대해 자세히 설명하십시오.
Michael Burr

1
Javascript는 강력한 형식입니다. 정적으로 입력되지 않았습니다. 모든 유형 검사는 런타임에 발생하지만 (정적이 아닌 동적) 발생하며 메모리 손상을 방지합니다 (강력한 입력의 한 측면).
bendin

5
음, Norm Ramsey의 매우 좋은 대답이 나타내는 것처럼 "강하게 입력 한"및 "약한 입력"은 특별히 잘 정의 된 용어가 아닙니다. 또한 Javascript가 강력하게 입력되는 한, 일부는 ( "4"/ "2")가 유효한 Javascript 표현식이 아니라는 것을 나타낼 수 있다고 생각할 수 있습니다.
Michael Burr

5

C는 정적으로 형식화 된 것으로 간주됩니다 (int에서 float로 변수를 변경할 수 없음). 변수가 선언되면 그런 식으로 고정됩니다.

그러나 유형이 플립 플롭 될 수 있기 때문에 약한 유형으로 간주됩니다.

0은 무엇입니까? '\ 0', FALSE, 0.0 등.

많은 언어에서는 조건이 부울 표현식의 부울 값만 가져 오기 때문에 IF (변수)라고 말할 수 없습니다. 이들은 더 강력한 형식입니다. 문자와 정수 사이를 이동할 때도 마찬가지입니다.

기본적으로 c에는 두 가지 주요 단순 데이터 유형, 정수 및 부동 소수점 숫자 (다양한 정밀도)가 있습니다. 그 밖의 모든 부울, 열거 형 (간단하지는 않지만 적합) 등은 그중 하나로 구현됩니다. 문자조차 기본적으로 정수입니다.

문자열 유형, 정의 된 값에만 할당 할 수있는 열거 형 유형, 부울 또는 참 / 거짓을 생성하는 표현식 만 사용할 수있는 부울 유형이있는 다른 언어와 비교하십시오.

그러나 Perl C에 비해 강력한 유형이라고 주장 할 수 있습니다. 그래서 이것은 유명한 주장 중 하나입니다 (vi vs emacs, linux vs windows 등). C #은 C보다 강력한 형식입니다. 기본적으로 어느 쪽이든 주장 할 수 있습니다. 그리고 당신의 대답은 아마도 양방향으로 갈 것입니다 :) 또한 일부 교과서 / 웹 페이지에서는 C가 약하게 입력되고 일부는 C가 강하게 입력되었다고 말합니다. 위키피디아에 가면 C 항목이 "부분적으로 약한 타이핑"이라고 말합니다. 파이썬 C에 비해 약한 유형이라고 말할 수 있습니다. 그래서 Python / C #, C, Perl은 연속체입니다.


Perl이 C보다 덜 강력하다는 이유를 설명해주십시오.
user51568

print "Testing"+ 0 # perl은 0을 수행합니다. $ var = "문자열"; $ var = 1; $ var = 123.4; 어떤 종류의 변수입니까?
Cervo

C에서 * test = "testing"; printf (테스트 + 0); 여전히 문자열이 될 것입니다. C에서 0 대신 숫자를 사용하면 인덱스가 변경됩니다. 여전히 약하지만 펄보다 약간 더 강합니다. char * 테스트; test = 0; 테스트 = 123.4; 테스트 = "c"를, ... 내 컴파일러는 오류를 생성
세르

오류는 캐스트가 필요하다는 것을 나타냅니다. 그래도 Perl보다 유형 검사가 약간 더 강하므로 연속체에서 C가 Perl보다 더 강력하다고 말해야합니다. 여전히 test = (char *)로 가서 0, 123.4, 'C'등을 사용할 수 있습니다.하지만 그냥하는 것은 오류입니다.
Cervo

4

여기에 많은 좋은 답변이 있습니다. Real World Haskell 에서 중요한 점을 말씀 드리고 싶습니다 .

많은 언어 커뮤니티가 "강력한 유형"에 대한 자체 정의를 가지고 있다는 사실을 아는 것이 유용합니다. 그럼에도 불구하고 우리는 타입 시스템의 강점 개념에 대해 짧고 폭넓게 이야기 할 것입니다.

(한조각)

활자체를 둘러싼 불꽃 놀이는 사람들이 "약함"과 "강함"이라는 단어에 가치관을 붙이는 평범한 영어에 뿌리를두고 있습니다. 우리는 보통 힘을 약점보다 낫다고 생각합니다. 더 많은 프로그래머가 학문적 전문 용어보다 평범한 영어를 사용하며, 학자들은 실제로 자신의 취향에 맞지 않는 유형 시스템에 벽돌 박쥐를 던지고 있습니다. 그 결과 종종 인기있는 인터넷 오락, 화염 전쟁이 발생합니다.

따라서 C 및 C ++에 대한 답변을 살펴 보지만 '강함'과 '약함'은 '좋음'과 '나쁨'에 매핑되지 않습니다.


4

Dennis Ritchie ( C의 창시자 )와 Brian Kernighan에 따르면 C는 강력한 유형의 언어가 아닙니다. 다음 줄은 책 The C 프로그래밍 언어 3 페이지 5 단락입니다.

C는 강력한 유형의 언어가 아니지만 진화함에 따라 유형 검사가 강화되었습니다.


3

제 생각에는 C / C ++는 강력한 형식입니다. 유형을 변환 할 수있는 해킹 유형 (void *)은 C가 머신에 가깝기 때문에 존재합니다. 즉, Pascal에서 어셈블러 명령을 호출하고 포인터를 조작 할 수 있으며 Pascal은 여전히 ​​강력한 형식의 언어로 간주됩니다. JNI를 통해 Java에서 어셈블러 및 C 실행 파일을 호출 할 수 있지만 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는 일하지 않습니다
alinsoar

0

C는 컴파일러 / 플랫폼이 지시하는 것처럼 강력하게 입력되었다고 말할 수 있습니다. 예를 들어 엄격한 플랫폼에서 빌드하는 경우 유형 punned 포인터를 역 참조하면 중단 될 수 있습니다.

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

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

이제 컴파일러에게 엄격한 앨리어싱을 건너 뛰라고하면 문제가되지는 않지만 이식성이별로 없습니다. 따라서 그런 의미에서 언어의 한계를 뛰어 넘는 것은 가능하지만 아마도 최선의 아이디어는 아닐 것입니다. 그것은 전형적인 캐스팅을 넘어서서, 즉 int를 길게 캐스팅하고 실제로 void의 가능한 함정 중 하나를 보여줍니다.

따라서 C는 기본적으로 엄격하게 형식화되어 있지만 다양한 컴파일러는 프로그래머가 가장 잘 알고 있고 유연성을 허용한다고 가정합니다. 이것은 실제로 컴파일러에 따라 다르며 일부는 잠재적 인 죄송합니다. 따라서 그런 의미에서 선택한 컴파일러는 질문에 답할 때 실제로 역할을합니다. 옳은 것은 종종 컴파일러가 당신이 벗어날 수 있도록 허용하는 것과 다릅니다.



-1

강력하게 입력되지 않았습니다.

다음 함수 프로토 타입이 인수의 데이터 유형에 대해 알려주는 내용을 고려하십시오.

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

아무것도. 따라서 여기에는 강력한 타이핑이 적용되지 않는 것이 좋습니다.


어? 그것은 당신에게 int가 있고, 그 뒤에 char, 그리고 모든 유형의 인수가 오는 것을 알려줍니다. 그것은 "아무것도"가 아닙니다.
Lawrence Dol

...는 전달되는 인수의 유형에 대해 알려주지 않습니다. 함수 자체 의 유형을 아는 것은 사실입니다. 그것이 Software Monkey가 말한 것입니다.
Johannes Schaub-litb

이러한 "모든 유형의 인수"는 제가 말하는 것입니다. 체인은 가장 약한 링크만큼만 강합니다.
joel.neely

-3

모든 표현식이 그 값의 함수가 아닌 유형을 가지고 있기 때문에 이것이 강력한 유형이라고 말하고 싶습니다. ei는 런타임 전에 알 수 있습니다.

OTOH 이것이 강력하게 입력 된 올바른 설명인지 잘 모르겠습니다. 언어에 대한 이유를 알 수있는 유일한 강력한 주장은 유형 캐스트, 공용체, 다른 언어로의 호출, 포인터, 어셈블리 언어 등을 통해 런타임에 유형 시스템을 파괴 할 수 없다는 보장입니다. 이와 같은 언어 존재하지만 너무 불구가되어 높은 확신과 학계를 벗어난 프로그래머에게는 그다지 관심이없는 것 같습니다. 누군가가 지적했듯이 실제로 제대로 수행하려면 다음과 같은 유형이 필요하기 시작 nonZeroInt합니다. 왝.


3
그렇지 않은 것은 무엇입니까? 강력한 유형 또는 C의 내 정의?
BCS
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.