C 및 C ++ 모두에서 유효한 코드가 각 언어로 컴파일 될 때 다른 동작을 생성 할 수 있습니까?


664

C와 C ++에는 많은 차이점이 있으며 모든 유효한 C 코드가 유효한 C ++ 코드는 아닙니다.
""유효한 "이란 정의 된 동작을 가진 표준 코드를 의미합니다 (즉, 구현 별 / 정의되지 않은 등).

C와 C ++ 모두에서 유효한 코드 가 각 언어의 표준 컴파일러로 컴파일 될 때 다른 동작을 생성하는 시나리오가 있습니까?

합리적이고 유용한 비교를하기 위해 (질문에서 명백한 허점을 찾으려고 시도하지 않고 실제로 유용한 것을 배우려고합니다) 가정 해 봅시다.

  • 전 처리기 관련 없음 ( #ifdef __cplusplus, pragma 등으로 해킹하지 않음 )
  • 구현에 정의 된 것은 두 언어 모두에서 동일합니다 (예 : 숫자 제한 등).
  • 우리는 각 표준의 합리적으로 최신 버전 (예 : C ++ 98 및 C90 이상)을 비교
    하고 있습니다. 버전이 중요한 경우 각 버전이 다른 동작을하는 것을 언급하십시오.

11
그건 그렇고, C와 C ++ 인 방언으로 동시에 프로그래밍하는 것이 유용 할 수 있습니다. 나는 과거에 하나의 현재 프로젝트 인 TXR 언어를 사용했습니다. 흥미롭게도 루아 언어의 개발자들도 같은 일을했으며이 방언을 "Clean C"라고 부릅니다. 더 나은 컴파일 시간 확인 및 C ++ 컴파일러의 유용한 진단 기능을 활용할 수 있지만 C 이식성은 유지됩니다.
Kaz

9
더 많은 견해와 찬란한 답변이 있기 때문에 이전 질문을이 질문에 병합했습니다. 이것은 여전히 ​​비 건설적인 질문의 예이지만, 그렇기 때문에 꽤 경계입니다 .SO 사용자에게 무언가를 가르치는 것입니다. 병합하기 전에 질문의 상태를 반영하기 위해 건설적이지 않은 것으로 닫았습니다. 동의하지 않고 다시여십시오.
George Stocker

13
"예"라고 답한 뒤에 객관적으로 대답 할 수 있다고 생각되는 것처럼 다시 열리기 투표 (아래에서 증명 됨). 사람들이 관련 행동을 배울 수 있다는 것이 건설적인 것이라고 생각합니다.
Anders Abel

6
@AndersAbel 순수한 정답 수는 모두 정답이며, 목록에 남는 질문으로 남아 있음을 분명하게 보여줍니다. 목록을 얻지 않고이 질문을 할 수있는 방법은 없었습니다.
dmckee --- 전 운영자 고양이 새끼

2
@dmckee 그 가치가있는 것에 동의합니다. 그러나 C ++ 태그 사람들은 ... 우리가 말해야 할 것은 ... feisty .
George Stocker

답변:


397

C와 C ++에서 유효한 다음과 같은 결과 i는 C와 C ++ 에서 다른 값을 갖게 될 것입니다.

int i = sizeof('a');

차이점에 대한 설명은 C / C ++에서 문자 크기 ( 'a')를 참조하십시오 .

이 기사 에서 다른 하나 :

#include <stdio.h>

int  sz = 80;

int main(void)
{
    struct sz { char c; };

    int val = sizeof(sz);      // sizeof(int) in C,
                               // sizeof(struct sz) in C++
    printf("%d\n", val);
    return 0;
}

8
확실히 이것을 기대하지 않았습니다! 좀 더 극적인 것을 원했지만 이것은 여전히 ​​유용합니다. 감사합니다. :) +1
user541686

17
+1 두 번째 예제는 C ++에서 struct구조체 이름 앞에 필요하지 않다는 점에서 좋은 예입니다 .
세스 카네기

1
@Andrey 나는 오래 전에 같은 생각을하고 테스트했으며 내 기대와 달리 표준없이 GCC 4.7.1에서 작동했습니다. GCC의 버그입니까?
세스 카네기

3
@SethCarnegie : 부적합한 프로그램이 작동 할 필요는 없지만 작동하지 않을 수도 있습니다.
Andrey Vihrov

3
struct sz { int i[2];};C와 C ++ 다른 값을 만들어야 한다는 것을 의미 합니다. sizeof (int) == 1 인 DSP 는 같은 값을 생성 할 수 있습니다.
Martin Bonner는 Monica

464

다음은 C와 C ++에서 함수 호출과 객체 선언의 차이점과 C90이 선언되지 않은 함수의 호출을 허용한다는 사실을 이용하는 예입니다.

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

C ++에서는 임시 f가 생성되어 소멸 되므로 아무것도 인쇄하지 않지만 C90에서는 hello선언하지 않고 함수를 호출 할 수 있기 때문에 인쇄 합니다.

이름 f이 두 번 사용되는 것에 대해 궁금한 경우 C 및 C ++ 표준에서 명시 적으로 허용 struct f하고 구조를 원한다면 명확하게 말 하거나 struct함수를 원한다면 떠나야 할 객체를 만들 수 있습니다 .


7
"int f ()"의 선언이 "int main ()"의 정의를
따르기

15
@Sogartar, 정말로? codepad.org/STSQlUhh C99 컴파일러는 경고 메시지를 표시하지만 여전히 컴파일 할 수 있습니다.
jrajav

22
C 함수의 @Sogartar는 암시 적으로 선언 될 수 있습니다.
Alex B

11
@AlexB C99 및 C11에 없습니다.

6
@jrajav 그렇다면 C99 컴파일러는 아닙니다. C99 컴파일러는 선언되지 않은 식별자를 구문 오류로 감지합니다. 이를 수행하지 않는 컴파일러는 C89 컴파일러 또는 사전 표준 또는 다른 부적합 컴파일러입니다.

430

C ++ 대 C90의 경우 구현이 정의되지 않은 다른 동작을 얻는 방법이 적어도 하나 있습니다. C90에는 한 줄 주석이 없습니다. 약간의주의를 기울이면 C90과 C ++에서 완전히 다른 결과를 가진 표현식을 작성할 수 있습니다.

int a = 10 //* comment */ 2 
        + 3;

C ++에서는 //줄 끝에서 끝까지 모든 것이 주석이므로 다음과 같이 작동합니다.

int a = 10 + 3;

C90에는 한 줄 주석이 없으므로 주석 만 /* comment */있습니다. 첫 번째 /2는 모두 초기화의 일부이므로 다음과 같이 나타납니다.

int a = 10 / 2 + 3;

따라서 올바른 C ++ 컴파일러는 13을 제공하지만 엄격하게 올바른 C90 컴파일러 8을 제공합니다. 물론 여기서는 임의의 숫자를 선택했습니다. 다른 숫자를 적절하게 사용할 수 있습니다.


34
이건 정말 놀랍습니다 !! 가능한 모든 것들 중에서 나는 행동 하하를 바꾸는 데 주석이 사용될 수 있다고 생각하지 않았을 것입니다. +1
541686

89
이 없어도 어느 것이 유효한지 (단항 +) 2읽습니다 10 / + 3.
Benoit

12
이제 재미있게, C와 C ++가 서로 다른 산술 표현식을 계산하여 동일한 결과로 계산하도록 수정하십시오.
Ryan C. Thompson

21
@RyanThompson 사소한. s / 2 / 1 /
sehe

4
@Mehrdad 내가 잘못했거나 의견이 전 처리기 관련입니까? 따라서 귀하의 질문에서 가능한 답변으로 제외되어야합니다! ;-)
Ale

179

C90 vs. C ++ 11 ( intvs. double) :

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

C에서 auto지역 변수를 의미합니다. C90에서는 변수 또는 함수 유형을 생략해도됩니다. 기본값은 int입니다. C ++ 11에서 auto완전히 다른 것을 의미하는 것은 변수를 초기화하는 데 사용되는 값에서 변수 유형을 유추하도록 컴파일러에 지시합니다.


10
C90은 auto?
세스 카네기

22
@SethCarnegie : 예, 스토리지 클래스입니다. 생략하면 기본적으로 발생하므로 아무도 사용하지 않았으며 의미가 변경되었습니다. 나는 그것이 int기본적으로 생각합니다 . 이것은 영리하다! +1
541686

5
C11에는 암시 적이 없습니다 int.
R .. GitHub 중지 지원 얼음

23
@KeithThompson 아, 추론을 의미한다고 생각합니다 int. 그럼에도 불구하고 많은 레거시 코드가 있고 시장 리더가 여전히 C99를 구현하지 않았으며 그렇게 할 의도가없는 실제 세계에서는 "C의 구식 버전"에 대한 이야기는 터무니 없습니다.
Jim Balter

11
"모든 변수는 반드시 명시적인 스토리지 클래스를 가져야합니다. 여러분의 진정한 관리입니다."
btown

120

아직 언급하지 않은 또 다른 예는 전 처리기의 차이점을 강조한 것입니다.

#include <stdio.h>
int main()
{
#if true
    printf("true!\n");
#else
    printf("false!\n");
#endif
    return 0;
}

C에서 "false"를 인쇄하고 C ++에서 "true"를 인쇄합니다. C에서 정의되지 않은 매크로는 0으로 평가됩니다. C ++에서는 1 개의 예외가 있습니다. "true"는 1로 평가됩니다.


2
흥미 롭군 누구든지이 변화의 근거를 알고 있습니까?
antred

3
"true"는 키워드 / 유효한 값이므로 "true value"(양의 정수와 마찬가지로)와 마찬가지로 true로 평가됩니다. 당신은 여전히 너무 "거짓"C ++에서 인쇄 #DEFINE 허위 사실을 수행 할 수 있습니다)
CoffeDeveloper

22
#define true false ಠ_ಠ
Bryan Boettcher '

2
@DarioOO는 UB에서 그러한 재정의 결과를 얻지 않습니까?
Ruslan

3
@DarioOO : 네, 당신은 틀 렸습니다. 키워드의 재정의는 허용되지 않으며 처벌은 운명으로 남습니다 (UB). 전처리 기는 견딜 수없는 별도의 컴파일 단계입니다.
중복 제거기

108

C ++ 11 표준에 따라 :

ㅏ. 쉼표 연산자는 C에서 lvalue에서 rvalue 로의 변환을 수행하지만 C ++에서는 수행하지 않습니다.

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

C ++에서이 표현식의 값은 100이되고 C에서이 값은입니다 sizeof(char*).

비. C ++에서 열거 자의 유형은 열거입니다. C에서 열거 자의 유형은 int입니다.

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

이는 sizeof(int)같지 않을 수 있음을 의미합니다 sizeof(E).

씨. C ++에서 빈 매개 변수 목록으로 선언 된 함수는 인수를 사용하지 않습니다. C 빈 매개 변수 목록에서 함수 매개 변수의 수와 유형을 알 수 없음을 의미합니다.

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C

첫 번째는 Alexey와 마찬가지로 구현 정의입니다. 그러나 +1.
세스 카네기

1
@Seth, 위의 모든 자료는 C ++ 11 표준의 Annex C.1에서 직접 가져온 것입니다.
Kirill Kobelev

예. 그러나 여전히 구현 정의되어 있습니다. sizeof(char*)이 경우 첫 번째 예제는 C 및 C ++에서 동일한 관찰 가능한 동작을 생성합니다 (즉, 획득 방법 s이 다르 더라도 s결국 100 임). OP는 언어 변호사 답변을 피하고 싶기 때문에 이러한 유형의 구현 정의 동작이 훌륭하다고 언급 했으므로 첫 번째 예외는 예외입니다. 그러나 두 번째는 어쨌든 좋습니다.
세스 카네기

5
쉬운 수정이 있습니다. 예제를 다음과 같이 변경하십시오.char arr[sizeof(char*)+1]; int s = sizeof(0, arr);
Mankarse

5
구현 정의 된 차이점을 피하기 위해을 사용할 수도 있습니다 void *arr[100]. 이 경우 요소의 크기는 같은 요소에 대한 포인터와 크기가 같으므로 두 개 이상의 요소가있는 경우 배열은 첫 번째 요소의 주소보다 커야합니다.
finnw

53

이 프로그램 1은 C ++ 및 C로 인쇄 됩니다 0.

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

int main(void)
{
    int d = (int)(abs(0.6) + 0.5);
    printf("%d", d);
    return 0;
}

이 때문에 발생 double abs(double), C ++의 과부하 때문에 abs(0.6)반환 0.6C에서 반환 동안 0때문에 호출하기 전에 암시 더블 - 투 - INT 변환의 int abs(int). C에서는을 사용 fabs하여 작업해야 double합니다.


5
그 문제를 가진 다른 사람의 코드를 디버깅해야했습니다. 오, 내가 그것을 좋아하는 방법. 어쨌든 프로그램은 C ++로 0을 인쇄합니다. C ++는 0 returnin 비교 첫 번째 참조 헤더 "cmath"를 사용할 필요가 ideone.com/0tQB2G 1 복귀 2 일 ideone.com/SLeANo을
CoffeDeveloper

디버깅을 통해이 차이점을 찾는 유일한 사람이 아니라는 점에 대해 기쁘게 생각합니다. VS2013에서 방금 테스트 한 결과,이 내용의 파일 만 포함 된 빈 파일은 확장자가 .cpp 인 경우 1을, 확장자가 .c 인 경우 0을 출력합니다. <math.h>가 VS에 간접적으로 포함 된 것 같습니다.
Pavel Chikulaev

VS C ++ 에서처럼 <math.h>는 C ++ 내용을 전역 네임 스페이스에 포함하지만 GCC는 그렇지 않습니다. 그러나 표준 동작인지 확실하지 않습니다.
Pavel Chikulaev

2
이 특정 코드 샘플 구현에 의존 : stdlib.h오직 정의 abs(int)abs(long); 버전 abs(double)은에 의해 선언됩니다 math.h. 따라서이 프로그램은 여전히 abs(int)버전을 호출 할 수 있습니다 . 포함 여부 stdlib.h도 구현 세부 사항 math.h입니다. (나는 abs(double)호출 된 경우 버그 일 것이라고 생각 하지만 다른 사양은 math.h포함되지 않았습니다).
MM

1
두 번째 문제는 C ++ 표준에 <math.h>포함하면 추가 과부하도 포함 된다고 말하는 것 같습니다. 실제로 모든 주요 컴파일러에는 양식 <cmath>을 사용 하지 않는 한 이러한 과부하가 포함되어 있지 않습니다 .
MM

38
#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

C에서는 sizeof(int)현재 시스템 의 값이 무엇이든 인쇄 4합니다. 일반적으로 오늘날 대부분의 시스템에서 일반적으로 사용됩니다.

C ++에서는 1을 인쇄해야합니다.


3
예, 실제로이 트릭에 익숙했습니다 .'c '는 C의 정수이고 C ++의 문자이지만 여전히 여기에 나열하는 것이 좋습니다.
Sean

9
즉 흥미로운 인터뷰 질문을 만들 것 - 특히 자신의 이력서에 C / C ++ 전문가를 넣어 사람들을 위해
마틴 베켓에게

2
그럼에도 불구하고 종류의. sizeof의 전체 목적은 유형의 크기를 정확히 알 필요가 없습니다.
Dana the Sane

13
C에서 값은 구현이 정의되고 1은 가능성입니다. (C ++에서는 명시된대로 1을 인쇄해야합니다.)
Windows 프로그래머

3
실제로 두 경우 모두 정의되지 않은 동작이 있습니다. %d에 대한 올바른 형식 지정자가 아닙니다 size_t.
R .. GitHub 중지 지원 얼음

37

또 다른 sizeof함정 : 부울 식.

#include <stdio.h>
int main() {
    printf("%d\n", (int)sizeof !0);
}

sizeof(int)표현식은 유형 int이지만 C ++에서는 일반적으로 1 이기 때문에 C 와 같습니다 (필요하지는 않지만). 실제로 그들은 거의 항상 다릅니다.


6
하나면 !충분합니다 bool.
Alexey Frunze

4
!! 부울 변환 연산자 int입니다 :)
EvilTeach

1
sizeof(0)입니다 4때문에 모두 C 및 C ++의 0정수를 rvalue입니다. sizeof(!0)이다 4C와 1C ++에서. 논리 NOT은 bool 유형의 피연산자에서 작동합니다. int 값이 0암시 적으로 false(bool rvalue) 로 변환되면 뒤집어지고 결과가됩니다 true. 모두 truefalseC ++에서 부울 우변은과가 sizeof(bool)있다 1. 그러나 C 에서는 int 유형의 rvalue 인로 !0평가됩니다 1. C 프로그래밍 언어에는 기본적으로 bool 데이터 유형이 없습니다.
Galaxy

26

C ++ 프로그래밍 언어 (제 3 판) 는 세 가지 예를 제공합니다.

  1. @Adam Rosenfield가 언급했듯이 sizeof ( 'a');

  2. // 숨겨진 코드를 만드는 데 사용되는 주석 :

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
  3. 예제와 같이 범위 밖의 물건을 숨기는 구조 등.



21

C ++ 표준에 의해 나열된 또 하나 :

#include <stdio.h>

int x[1];
int main(void) {
    struct x { int a[2]; };
    /* size of the array in C */
    /* size of the struct in C++ */
    printf("%d\n", (int)sizeof(x)); 
}

패딩 차이가 발생합니까?
v.oddou

아 죄송합니다 x. 상단에 다른 것이 있습니다. 나는 당신이 "배열 a" 이라고 생각했다 .
v.oddou

20

C의 인라인 함수는 기본적으로 C ++의 인라인 함수가 아닌 외부 범위로 설정됩니다.

다음 두 파일을 함께 컴파일하면 GNU C의 경우 "I in inline"이 인쇄되지만 C ++에는 아무것도 인쇄되지 않습니다.

파일 1

#include <stdio.h>

struct fun{};

int main()
{
    fun();  // In C, this calls the inline function from file 2 where as in C++
            // this would create a variable of struct fun
    return 0;
}

파일 2

#include <stdio.h>
inline void fun(void)
{
    printf("I am inline\n");
} 

또한 C ++ 는 기본값 인 C와 달리 명시 적으로 선언되지 않는 한 모든 const전역을 암시 적으로 처리합니다 .staticexternextern


정말 그렇게 생각하지 않습니다. 아마 당신은 요점을 놓쳤습니다. 코드를 유효한 C ++로 만드는 데 사용되는 struct st의 정의에 관한 것이 아닙니다. 요점은 c 대 c ++에서 인라인 함수의 다른 동작을 강조한다는 것입니다. extern에도 동일하게 적용됩니다. 이들 중 어느 것도 어떤 솔루션에서도 논의되지 않습니다.
fkl

2
인라인 함수의 다른 동작은 무엇이며 extern여기에 설명되어 있습니까?
세스 카네기

꽤 명확하게 작성되었습니다. "c ++의 인라인 함수는 c ++의 인라인 함수가 아닌 외부 범위로 설정됩니다 (코드에서 알 수 있음). 또한 C ++은 extern이 기본값 인 C와 달리 명시 적으로 extern으로 선언되지 않는 한 모든 const를 전역으로 파일 범위로 처리합니다. "예를 들어 만들 수 있습니다." 나는 당황합니다-이해할 수 없습니까?
fkl

12
@fayyazkl 표시된 동작은 조회 차이 ( struct funvs fn) 때문일 뿐이며 함수가 인라인인지 여부와는 관련이 없습니다. inline한정자 를 제거하면 결과는 동일합니다 .
Alex B

3
ISO C에서는이 프로그램이 잘못 구성되었습니다. inlineC99까지는 추가되지 않았지만 C99 fun()에서는 범위 내 프로토 타입 없이는 호출 할 수 없습니다. 따라서이 답변은 GNU C에만 적용된다고 가정합니다.
MM

16
struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

C ++에서 종료 코드 0 또는 C에서 3을 리턴합니다.

이 트릭은 아마도 더 흥미로운 것을 수행하는 데 사용될 수 있지만 C에 적합 할 생성자를 만드는 좋은 방법을 생각할 수 없었습니다. 휴대가 불가능한 방식으로 전달 되더라도 :

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

그러나 VC ++ 2005는 "종료 코드"가 어떻게 재정의되는지에 대해 불평하면서 C ++ 모드에서 컴파일을 거부했습니다. (프로그래밍 방법을 잊어 버리지 않는 한 이것이 컴파일러 버그라고 생각합니다.) C로 컴파일 할 때 프로세스 종료 코드 1로 종료되었습니다.


exit를 사용하는 두 번째 예제는 불행히도 gcc 또는 g ++에서 컴파일되지 않습니다. 그래도 좋은 생각입니다.
Sean

1
exit(code)분명히 code유형 의 변수 에 대한 유효한 선언입니다 exit. (이것은 다르지만 비슷한 문제인 "가장 vexing 구문 분석"을 참조하십시오).
user253751

16
#include <stdio.h>

struct A {
    double a[32];
};

int main() {
    struct B {
        struct A {
            short a, b;
        } a;
    };
    printf("%d\n", sizeof(struct A));
    return 0;
}

이 프로그램 은 C ++ 컴파일러를 사용하여 컴파일 할 때 128( 32 * sizeof(double))를 인쇄 하고4 사용하여 컴파일 할 때 .

C에는 스코프 해상도의 개념이 없기 때문입니다. 다른 구조에 포함 된 C 구조에서는 외부 구조의 범위에 포함됩니다.


이것은 흥미 롭다! (나는 당신 32*sizeof(double)이 32보다는 오히려 의미 하는 것 같아요 :)
user1354557

3
다음을 사용하여 인쇄 size_t하여%d
받으십시오.

7

C와 C ++ 전역 네임 스페이스의 차이점을 잊지 마십시오. foo.cpp 가 있다고 가정하십시오.

#include <cstdio>

void foo(int r)
{
  printf("I am C++\n");
}

그리고 foo2.c

#include <stdio.h>

void foo(int r)
{
  printf("I am C\n");
}

이제 main.cmain.cpp 가 다음과 같이 있다고 가정합니다 .

extern void foo(int);

int main(void)
{
  foo(1);
  return 0;
}

C ++로 컴파일되면 C ++ 전역 네임 스페이스의 기호를 사용합니다. C에서는 C를 사용합니다.

$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test 
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test 
I am C

연결 사양을 의미합니까?
user541686

이름 맹 글링. C ++ 이름은 C 동안 접두사와 접미사를하지 않은
CoffeDeveloper

이름 맹 글링은 C ++ 사양의 일부가 아닙니다. C에서는 금지되어 있습니까?
skyking

5
이것은 정의되지 않은 동작입니다 (의 다중 정의 foo). 별도의 "글로벌 네임 스페이스"가 없습니다.
MM

4
int main(void) {
    const int dim = 5; 
    int array[dim];
}

이것은 C ++ 및 C99, C11 및 C17에서 유효하다는 점에서 다소 특이합니다 (C11, C17에서는 선택 사항 임). C89에서는 유효하지 않습니다.

C99 +에서는 컴파일 타임 형식 대신 런타임 형식이 있고 sizeof arrayC에서는 정수 상수식이 아니기 때문에 일반 배열에 대해 고유 한 가변 길이 배열을 만듭니다 . C ++에서는 형식이 완전히 정적입니다.


여기에 이니셜 라이저를 추가하려고하면 :

int main(void) {
    const int dim = 5; 
    int array[dim] = {0};
}

가변 길이 배열 은 이니셜 라이저를 가질 수 없으므로 유효한 C ++이지만 C 는 아닙니다.


0

이것은 C 및 C ++의 lvalue 및 rvalue와 관련이 있습니다.

C 프로그래밍 언어에서 사전 증분 및 사후 증분 연산자는 모두 lvalue가 아니라 rvalue를 반환합니다. 이는 =할당 연산자 의 왼쪽에있을 수 없음을 의미합니다 . 이 두 명령문 모두 C에서 컴파일러 오류를 발생시킵니다.

int a = 5;
a++ = 2;  /* error: lvalue required as left operand of assignment */
++a = 2;  /* error: lvalue required as left operand of assignment */

그러나 C ++에서 증분 사전 연산자는 lvalue를 리턴 하고 사후 증분 연산자는 rvalue를 리턴합니다. 사전 증가 연산자가있는 표현식을 =대입 연산자 의 왼쪽에 배치 할 수 있음을 의미합니다 !

int a = 5;
a++ = 2;  // error: lvalue required as left operand of assignment
++a = 2;  // No error: a gets assigned to 2!

왜 이럴까요? 후행 증가는 변수를 증가시키고 이전 과 같이 변수를 반환합니다. 증가시키고 증가가 발생 . 이것은 실제로 rvalue 일뿐입니다. 변수 a의 이전 값은 임시로 레지스터에 복사 된 다음 a가 증가합니다. 그러나 이전의 a 값은 표현식에 의해 리턴되며 rvalue입니다. 더 이상 변수의 현재 내용을 나타내지 않습니다.

사전 증분은 먼저 변수를 증분 다음 증분이 발생한 변수를 반환합니다 . 이 경우 변수의 이전 값을 임시 레지스터에 저장할 필요가 없습니다. 변수가 증가한 후에 변수의 새 값을 검색합니다. 따라서 사전 증분은 lvalue를 반환하고 변수 자체를 반환합니다. 우리는이 lvalue를 다른 것에 할당 할 수 있습니다. 다음 문장과 같습니다. 이것은 lvalue를 rvalue로 암시 적으로 변환 한 것입니다.

int x = a;
int x = ++a;

사전 증분은 lvalue를 반환하기 때문에 무언가를 할당 할 수도 있습니다. 다음 두 문장은 동일합니다. 두 번째 할당에서는 먼저 a가 증가한 다음 새 값이 2로 덮어 씁니다.

int a;
a = 2;
++a = 2;  // Valid in C++.

3
여기에는 "C에서 유효"하지 않습니다.
o11c

0

빈 구조체의 크기는 C에서 0이고 C ++에서 1입니다.

#include <stdio.h>

typedef struct {} Foo;

int main()
{
    printf("%zd\n", sizeof(Foo));
    return 0;
}

1
차이점은 C는 컴파일러 확장을 제외하고는 빈 구조를 가지고 있지 않다는 것입니다. 즉,이 코드는 "C와 C ++ 모두에서 유효합니다"와 일치하지 않습니다
Antti Haapala
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.