sizeof (my_arr) [0]이 컴파일되고 sizeof (my_arr [0])과 같은 이유는 무엇입니까?


129

이 코드는 왜 컴파일됩니까?

_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");

첫 번째 두 가지 주장은 분명히 정확하지만 내 이해는 sizeof()정수 리터럴로 평가해야하며 배열로 취급 할 수 없기 때문에 마지막 줄이 실패 할 것으로 예상했을 것 입니다. 즉, 다음 줄이 실패하는 것과 같은 방식으로 실패합니다.

_Static_assert(4[0] == 4, "");

흥미롭게도, 다음은 실제로 컴파일에 실패합니다 (같은 작업을 수행해야합니까?).

_Static_assert(*sizeof(my_arr) == 4, "");

오류 : 단항 '*'의 유효하지 않은 유형 인수 ( 'long unsigned int'가 있음) _Static_assert (* sizeof (my_arr) == 4, "");

중요한 경우 gcc 5.3.0을 사용하고 있습니다.


15
나는 ( sizeof( my_arr ) )[ 0 ]실패를 의심한다 .
Andrew Henle

최근 복제본에는이 구문에 대한 또 다른 변형이 있습니다. 왜 sizeof (x) ++가 컴파일됩니까?
Peter Cordes

답변:


197

sizeof기능이 아닙니다. !또는 과 같은 단항 연산자 ~입니다.

sizeof(my_arr)[0]로 파싱 sizeof (my_arr)[0]그냥, sizeof my_arr[0]중복 괄호.

이것은로 !(my_arr)[0]구문 분석하는 것과 같습니다 !(my_arr[0]).

C. 안으로 일반적 후위 연산자 프리픽스 사업자보다 높은 우선 순위를 가질 sizeof *a[i]++로 파싱 sizeof (*((a[i])++))(후위 연산자 []++인가되는 a제 다음 프리픽스 연산자 *sizeof ).

(이것은 표현 버전입니다 sizeof. 괄호로 묶인 유형 이름을 취하는 유형 버전도 있습니다.이 sizeof (TYPE)경우 sizeof구문 이 필요하고 구문의 일부가 됩니다.)


14
나는 sizeof가 단항 연산자이고 함수가 아니라는 것을 완전히 알고 있었지만 완전히 잊었습니다. 웁스. 자세한 설명을 주셔서 감사합니다. []가 *보다 우선 순위가 높다는 사실은 관계없이 흥미 롭습니다.
bgomberg

@melpomene 재미있는. 나는 sizeof단항 연산자 라고 생각한 적이 없다 .
mutantkeyboard

5
당신은 의미하지 "... parses as sizeof (my_arr[0])"않습니까? 공백을 추가해도 실제로 아무것도 바뀌지 않습니다.
Bernhard Barker

sizeof((my_array)[0])대신 추천 합니다
bolov


46

sizeof두 개의 "버전"이 있습니다 : sizeof(type name)sizeof expression. 전자 ()는 논쟁의 여지 가 필요하다 . 그러나 후자는 식으로 주장하는 식으로 논쟁의 여지가 없다 (). ()인수에 사용하는 것이 무엇이든 인수 표현식의 일부로 간주됩니다.sizeof 구문 자체.

my_arr컴파일러에 유형 이름이 아닌 객체 이름으로 알려져 있기 때문에sizeof(my_arr)[0] 실제로는 컴파일러 sizeof가 표현식에 적용되는 것으로 간주됩니다 . sizeof (my_arr)[0]여기서 (my_arr)[0]인수 식은 어디 입니까? ()주변 배열 이름 순수 불필요하다. 전체 표현은로 해석됩니다 sizeof my_arr[0]. 이것은 이전과 같습니다 sizeof(my_arr[0]).

(이것은 BTW, 이전 버전 sizeof(my_arr[0])에도 불필요한 쌍이 포함되어 있음을 의미합니다 ().)

sizeof구문에는 어쨌든 ()논쟁 의 쌍이 필요 하다는 오해가 널리 퍼져 있습니다. 이러한 오해는 다음과 같은 표현을 해석 할 때 사람들의 직관을 오도하는 것입니다 sizeof(my_arr)[0].


1
첫 번째 버전은 컴퓨터에서 일반적으로 정수의 크기를 확인할 수 있도록 (64 비트 컴퓨터조차 없었던 때부터!) int유효한식이 아니므로 사용할 수 없습니다. 그것으로 두 번째 형태.
NH.

25

[]보다 우선 순위가 높습니다 sizeof. 그래서 sizeof(my_arr)[0]동일하다 sizeof((my_arr)[0]).

우선 순위 테이블에 대한 링크는 다음과 같습니다 .


8

sizeof표현식을 매개 변수로 사용하는 연산자 버전을 사용하고 있습니다. 유형을 취하는 것과 달리 괄호 필요 하지 않습니다 . 따라서 피연산자는 간단 (my_arr)[0]하며 괄호는 중복됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.