왜 자동 a = 1입니까? C로 컴파일?


125

코드:

int main(void)
{
    auto a=1;
    return 0;
}

파일의 확장명이 .c 인 경우 MS Visual Studio 2012 컴파일러에서 오류없이 컴파일됩니다. 나는 항상 .c 확장자를 사용할 때 컴파일은 C ++이 아닌 C 구문을 따라야한다고 생각했습니다. 또한, 내가 아는 한 유형이없는 auto는 C ++ 11 이후 C ++ 에서만 허용 됩니다 .이 유형은 초기화 프로그램에서 유형이 추론됨을 의미합니다.

내 컴파일러가 C를 고수하지 않거나 코드가 실제로 C 언어로 정확합니까?


8
C ++ 모드 (가능)로 컴파일하거나 MS가 여전히 마지막 천년에 머물러 있습니다. 암시는 int1999 년에 C 표준에서 제거되었습니다
옌스 Gustedt에게

16
@JensGustedt MSVC ++는 C89 (및 C99의 일부 기능) 만 지원합니다. C ++ 컴파일러에 가깝습니다.
ntoskrnl

3
@Brandin : / Wall 옵션을 사용하면 C4431 경고가 발생하여 형식 지정자가 누락되었으며 기본 int가 더 이상 C에서 지원되지 않습니다 (Jens의 설명 참조). 분명히이 컴파일러는 그것을 지원하기 때문에 약간의 모순입니다 ...
lee77

4
@JensGustedt이 조치에 의해 2012 년에 출시 된 GCC 4.7 (및 이후 버전에서도 사용중인 제품이없는 것 같습니다)도 "마지막 밀레니엄에 갇혀 있습니다". 플래그를 지정하지 않은 경우 통지없이 OP의 코드를 컴파일합니다.

3
@delnan, 나는 최소한 OP가 경고 수준을 켠 것으로 가정했습니다. 분명히 틀렸다. 그리고 어떤 의미에서 gcc도 여전히 기본으로 C99 (또는 변형)가 없으므로 gcc가 붙어 있습니다. clang은 플래그가 없어도 구문에 대해 경고합니다.
Jens Gustedt

답변:


240

auto"로컬 범위"를 의미하는 이전 C 키워드입니다. auto aauto int a함수와 동일하며 함수 내에 선언 된 변수의 기본값은 로컬 범위이므로이 int a예제 와 동일 합니다.

이 키워드는 실제로 어떤 기본 유형 없었다 C의 전신 B,에서 남은입니다 : 모든했다 int포인터, int배열, int(*) 선언 중 하나가 될 것입니다. auto또는 extrn[원문]. C는 "모든 것이 int"를 기본 규칙으로 상속 했으므로 다음과 같이 정수를 선언 할 수 있습니다

auto a;
extern b;
static c;

ISO C는 이것을 제거했지만 많은 컴파일러는 여전히 이전 버전과의 호환성을 위해 그것을 승인합니다. 익숙하지 않은 경우 관련 규칙이 적용되고 있음을 알아야합니다.

unsigned d;  // actually unsigned int

현대 코드에서 여전히 일반적입니다.

C ++ 11은 키워드를 재사용했는데 C ++ 프로그래머가 형식 유추를 위해 원래의 의미로 사용하는 경우는 거의 없었습니다. intC 의 "모든 것 "규칙이 C ++ 98에서 이미 삭제 되었기 때문에 이것은 대부분 안전합니다 . 깨는 유일한 것은 auto T a어쨌든 아무도 사용하지 않은 것입니다. ( 언어의 역사에 관한 그의 논문 어딘가에 Stroustrup은 이것에 대해 언급하고 있지만 지금은 정확한 참고 문헌을 찾을 수 없습니다.)

(*) B에서의 문자열 처리는 흥미로웠다. int각 멤버에 여러 문자 배열을 사용하고 묶을 것이다 . B는 실제로 다른 구문을 가진 BCPL 이었습니다 .


7
아닙니다. 1999 년 이후로 이것은 합법적 인 C가 아닙니다.
Jens Gustedt

18
@JensGustedt VS는 최신 C 컴파일러를 제공한다고 주장하지 않습니다. 모든 모습에서 C 컴파일러에 대한 작업은 몇 년 전에 중단되었습니다. 그들은 사람들이 레거시 코드를 계속 컴파일 할 수 있도록 단지 그것을 제공합니다. (물론, 현대의 모든 C 컴파일러에는 레거시 코드를 지원하는 옵션이 있습니다. K & R C에 대한 옵션 포함)
James Kanze

23
@JensGustedt : 확실합니까? GCC와 Clang은 모두 C99 모드에서 경고하지만을 제외하고는 오류로 간주하지 않습니다 -Werror.
Fred Foo 2014 년

2
@larsman, 예, 6.7.2에는 다음과 같은 명시 적 제약이 있습니다. 각 선언의 선언 지정자에는 하나 이상의 유형 지정자가 주어져야합니다.
Jens Gustedt

40
@JensGustedt-re 아니오, 1999 년 이후로 합법적 인 C가 아닙니다. 괜찮은 현대적인 C 컴파일러는 이것을 허용하지 않습니다. 첫 번째 진술은 정확합니다. IMHO, 두 번째 진술은 잘못되었습니다. 괜찮은 현대 C 컴파일러는 이것을 허용해야합니다. 허용되지 않은 경우 다시 작성해야하는 모든 기존 코드를 살펴보십시오. 이 의견에 대한 답변을 작성했습니다.
David Hammen

35

이것은 No에 대한 답변이자 확장 된 주석입니다 . 1999 년 이래로 합법적 인 C가 아닙니다.

예, auto a=1;C1999 (및 C2011)에서는 불법입니다. 이것이 현재 불법이라고해서 현대 C 컴파일러가 그러한 구성을 포함하는 코드를 거부해야한다는 의미는 아닙니다. 괜찮은 현대 C 컴파일러가 여전히 이것을 허용해야한다고 정확히 반대 주장합니다.

clang과 gcc는 모두 1999 또는 2011 버전의 표준에 대해 문제의 샘플 코드를 컴파일 할 때 그렇게합니다. 두 컴파일러 모두 진단을 실행 한 후 불쾌감을주는 것처럼 진행되었습니다 auto int a=1;.

제 생각에는 괜찮은 컴파일러가해야 할 일입니다. clang과 gcc는 진단을 통해 표준을 완벽하게 준수합니다. 표준은 컴파일러가 불법 코드를 거부해야한다고 말하지 않습니다. 표준은 단지 번역 단위에 구문 규칙이나 제약 조건 (5.1.1.3)을 위반 한 경우 적합한 구현이 적어도 하나의 진단 메시지를 생성해야한다고 말합니다.

잘못된 구문이 포함 된 코드가 있으면 적절한 컴파일러는 잘못된 코드를 이해하여 컴파일러가 코드에서 다음 오류를 찾을 수 있도록합니다. 첫 번째 오류에서 멈추는 컴파일러는 그리 좋은 컴파일러가 아닙니다. auto a=1"implicit int"규칙을 적용 하는 방법이 있습니다 . 이 규칙은 컴파일러가 C90 또는 K & R 모드에서 사용될 때 auto a=1와 같이 컴파일러가 해석하도록 auto int a=1합니다.

대부분의 컴파일러는 일반적으로 잘못된 구문이 포함 된 거부 코드 (거부 : 개체 파일 또는 실행 파일 생성 거부)를 수행합니다. 컴파일러 작성자가 컴파일 실패가 최선의 선택이 아니라고 결정한 경우입니다. 가장 좋은 방법은 진단을 실행하고 코드를 수정 한 다음 수행하는 것입니다. 과 같은 구문으로 가득 찬 레거시 코드가 너무 많습니다 register a=1;. 컴파일러는 C99 또는 C11 모드에서 진단 코드를 사용하여 해당 코드를 컴파일 할 수 있어야합니다.


1
@larsmans-어디에서 왔는지 알 수 있습니다. 당신은 원하는 -ffs-please-stop-allowing-constructs-from-some-previous-millennium컴파일러 옵션, 또는 좀 더 간결하게하는 -fstrict-compliance옵션을 선택합니다. "-std = c11을 사용할 때 고대 K & R kruft가 컴파일 될 것으로 기대하지 않았습니다. 실제로는 컴파일 하지 않기를 원했습니다 !"
David Hammen

1
실제로 아니오, 최악의 크래프트를 컴파일하려면 플래그를 켜야 합니다 . 그러나 -std=c99더 엄격한 것은 올바른 방향으로의 발걸음이 될 것입니다 :)
Fred Foo

1
당신이 gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror(내가 일상적으로 사용하는 것, 심지어 질문에 대한 코드에서도)을 사용한다면, 당신은 당신이 원하는 것에 상당히 가깝습니다. 저는 GCC를 최소한 -std=c99바람직하게 -std=c11(또는 -std=gnu11; 가능할 가능성이 높음) 기본값으로 설정 하고 싶지만 그럴 때까지는… 옵션을 조정할 수 있습니다. -pedantic, -Wshadow, -Wold-style-declaration어떤 다른 사람이 유용 할 수 있지만,이 옵션의 설정 시작하는 것이 좋다.
Jonathan Leffler

3
@DavidHammen : 순환 적 복잡성, 프로젝트 관리자 또는 회사 정책 모두 언어의 요소가 아닙니다.
Jerry B

3
GCC에서 원하는 행동을 취하는 깃발은-pedantic-errors
τεκ

29

auto2011 표준 C과 그 C++이전에 의미가 있습니다. 변수에 자동 수명, 즉 scope에 의해 결정된 수명이 있음을 의미합니다 . 예를 들어 static수명과 는 달리 범위에 관계없이 변수가 "영구적으로"지속됩니다. auto기본 수명이며 명시 적으로 철자가 거의 없습니다. 이것이의 의미를 바꾸는 것이 안전한 이유입니다 C++.

이제 C99 표준 이전의 변수 유형을 지정하지 않으면 기본값은 int입니다.

따라서 범위에 따라 수명이 결정되는 변수를 auto a = 1;선언하고 정의 int합니다.

( "수명"은 "보존 기간"이라고하는 것이 더 적절하지만 덜 명확하다고 생각합니다).


자, 실제로 자동 a = 1은 C에서 허용되며 자동 저장 기간을 가진 int 변수를 의미합니다.
lee77

1
적절하게 "저장 기간"은 "자동", "정적", "동적", "스레드"값 목록 중 하나를 사용합니다. "수명"은 물체의 실제 수명입니다. 따라서 변수의 저장 기간은 "자동"이고 수명은 " main함수 범위의 기간 "입니다.
Steve Jessop

예 @ 스티브, 나는 그것을 암시하는 말은하지 않았다 autostatic유일한 두 가지 가능성이 있습니다. 나는 C++(그리고 C)에 익숙하지 않은 것처럼 보이는 사람을 겨냥한 방식으로 답변을 작성하려고 노력 했기 때문에 세부 사항에 대해 약간의 글을 썼습니다. 어쩌면 그것은 나쁜 생각이었습니다. 조만간 보험 적용이 필요합니다.
BoBTFish

1
@BoBTFish : 오, 나는 그것에 대해 불평하지 않았습니다. 나는 단지 지속 시간 인 "lifetime"과 "storage duration category"라고하는 더 정확하게 "storage duration"사이의 시맨틱 차이를 확장하려고했다.
Steve Jessop

이 암묵적인 int내용은 1999 년부터 C에서 제거되었습니다.
Jens Gustedt

8

C와 C ++의 역사적 방언 은 자동 저장 기능 auto이있는 키워드 의미입니다 a. 기본적으로 자동 인 로컬 변수에만 적용 할 수 있으므로 아무도 사용하지 않습니다. 이것이 바로 C ++이 키워드의 용도를 변경 한 이유입니다.

역사적으로 C는 형식 지정자가없는 변수 선언을 허용했습니다. 유형은 기본적으로 int입니다. 따라서이 선언은

int a=1;

나는 이것이 현대 C에서 더 이상 사용되지 않으며 (아마도 금지되어 있다고 생각한다); 그러나 일부 인기있는 컴파일러는 기본적으로 C90으로 설정되어 있으며 (필자가 생각하는 경우), 특별히 요청하면 경고 만 활성화합니다. 와 C99를 지정하거나 GCC로 컴파일하고 -std=c99, 또는 함께 경고를 활성화 -Wall또는 -Wimplicit-int경고를 제공합니다 :

warning: type defaults to int in declaration of a

4
그것은 실제로 1999 년부터 C에서 금지
옌스 Gustedt에게

5

C에서는 C ++ 11에서 auto와 동일한 기능을 register수행합니다. 즉, 변수에 자동 저장 기간이 있음을 의미합니다.

그리고 C99 이전의 C에서 (그리고 Microsoft 컴파일러는 C99 또는 C11을 지원하지 않지만 일부를 지원할 수는 있지만) 유형은 많은 경우 생략 될 수 있으며 기본값은로 설정됩니다 int.

이니셜 라이저에서 유형을 전혀 사용하지 않습니다. 호환되는 이니셜 라이저를 선택했습니다.


1
C ++ 11에서 레지스터 키워드가 더 이상 사용되지 않습니까?
sordid

@sordid 네, 그렇습니다. C ++ 11 이전 autoregister동일한 의미를 가지고 있었다 (나는 일찍 복용에 대한 제한이 있었다 논평 registerrestrict로 변수의 주소,하지만 C ++에 대한 정확). register더 이상 사용되지 않지만 현재는 이전 의미를 유지합니다.

5
@ JenGustedt : 대답은 그들이 아니라고 말합니다. 그것은 말한다 autoC에서와 같은 의미 register가 (모두 평균 자동 저장 기간, 아무것도)을 수행하는 C ++한다.
Mike Seymour

3

Visual Studio 컴파일 유형은에서 사용할 수 있습니다 right click on file -> Properties -> C/C++ -> Advanced -> Compile As. C 강제 /TC옵션 으로 컴파일되었는지 확인하려면 이 경우 larsmans가 말한 것입니다 (오래된 C auto키워드). 몰라도 C ++로 컴파일 될 수 있습니다.


3

스토리지 클래스는 C 프로그램 내 변수 및 / 또는 기능의 범위 (가시성) 및 수명을 정의합니다.

C 프로그램에서 사용할 수있는 스토리지 클래스는 다음과 같습니다.

auto
register
static
extern

auto 모든 로컬 변수의 기본 스토리지 클래스입니다.

{
        int Count;
        auto int Month;
}

위의 예제는 스토리지 클래스가 동일한 두 변수를 정의합니다. auto는 함수 내에서만 사용할 수 있습니다 (예 : 로컬 변수).

intauto아래 코드에서 기본 유형입니다 .

auto Month;
/* Equals to */
int Month;

아래 코드도 합법적입니다.

/* Default-int */
main()
{
    reurn 0;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.