printf("%x",1)가 정의되지 않은 동작을 호출합니까?
C 표준(6.5.2.2항 6)에 의거합니다.
호출된 함수를 나타내는 표현식이 프로토타입을 포함하지 않는 유형을 가질 경우 각 인수에 대해 정수 승격을 수행하고 유형 플로트가 있는 인수는 이중으로 승격합니다.이를 기본 인수 프로모션이라고 합니다.인수의 수가 매개 변수의 수와 같지 않으면 동작이 정의되지 않습니다.함수가 프로토타입을 포함하는 유형으로 정의되고 프로토타입이 생략(, ...)으로 끝나거나 승격 후 인수의 유형이 매개 변수의 유형과 호환되지 않으면 동작이 정의되지 않습니다.프로토타입이 포함되지 않은 유형으로 함수가 정의되고, 승격 후 인수의 유형이 승격 후 인수의 유형과 호환되지 않는 경우, 다음의 경우를 제외하고는 동작이 정의되지 않습니다.
- 하나의 승격된 유형은 부호 있는 정수 유형이고, 다른 승격된 유형은 해당하는 부호 없는 정수 유형이며, 값은 두 유형 모두에서 나타낼 수 있습니다.
- 두 유형 모두 문자 유형 또는 보이드의 정규 또는 비정규 버전에 대한 포인터입니다.
따라서 일반적으로 다음과 같이 통과하는 것은 잘못된 것이 없습니다.int
다음을 기대하는 가변 함수로unsigned int
전달된 값이 두 유형에 모두 적합한 한.그러나, 에 대한 사양은printf
(7.19.6.1항 9):
변환 규격이 올바르지 않으면 동작이 정의되지 않습니다.인수가 해당 변환 규격에 올바른 유형이 아닌 경우 동작이 정의되지 않습니다.
서명/비부호 불일치에 대해서는 예외가 없습니다.
이게 의미하는 바입니까?printf("%x", 1)
정의되지 않은 행동을 호출합니까?
저는 그것이 기술적으로 정의되지 않았다고 믿습니다, 왜냐하면 "올바른 유형" 때문입니다.%x
다음과 같이 명시되어 있습니다.unsigned int
- 지적하신 것처럼 서명/비부호 불일치에 대한 예외는 없습니다.
의 규칙은.printf
보다 특정한 경우에 대한 것이므로 일반적인 경우에 대한 규칙을 재정의합니다(특정한 경우가 일반적으로 통과하는 것이 허용됨).NULL
의 기능을 기대하고 있습니다.const char *
인수, 그러나 전달하는 것은 정의되지 않은 행동입니다.NULL
로.strlen()
).
저는 "기술적으로"라고 말합니다. 왜냐하면 표준의 다른 제약들을 고려할 때, 구현이 이 경우에 문제를 일으키려면 의도적으로 비뚤어질 필요가 있다고 생각하기 때문입니다.
아니요, %x는 서명되지 않은 int를 형식하고 상수 식 1의 유형은 int인 반면 값은 서명되지 않은 int로 표현할 수 있기 때문입니다.작업이 UB가 아닙니다.
이것은 정의되지 않은 동작으로, 정수 타입의 포인터를 반대 부호의 상보 타입으로 다시 해석하는 것과 같은 이유에서입니다.유감스럽게도 이것은 두 방향 모두에서 허용되지 않습니다. 하나의 유효한 표현은 다른 하나의 트랩 구현일 수 있기 때문입니다.
서명된 것부터 서명되지 않은 재해석까지 함정 표현이 존재할 수 있다는 것을 알 수 있는 유일한 이유는 서명되지 않은 유형이 단지 기호 비트를 가리는 왜곡된 기호 표현의 경우 때문입니다.불행히도 그러한 것은 표준의 6.2.6.2 기준으로 허용됩니다.이러한 아키텍처에서 서명된 유형의 모든 음수 값은 서명되지 않은 유형의 트랩 표현일 수 있습니다.
당신의 예에서 이것은 더 이상해요.1
서명되지 않은 형식에 대한 트랩 표현은 허용되지 않습니다.그래서 '진짜' 예를 들어보자면, 당신은 다음과 같은 질문을 해야 합니다.-1
.
사람들이 이러한 기능을 가진 C 컴파일러를 작성하는 아키텍처는 아직 존재하지 않는다고 생각합니다. 따라서 새로운 버전의 표준이 이 고약한 경우를 폐지할 수 있다면 확실히 라이브가 더 쉬워질 것입니다.
저는 그것이 정의되지 않았다고 믿습니다.변수 길이의 인수 목록을 가진 함수는 인수를 수락할 때 암시적 변환을 갖지 않으므로,1
에 캐스팅되지 않을 것입니다unsigned int
과거의 일로printf()
, 정의되지 않은 행동을 야기합니다.
TL;DR 그것은 UB가 아닙니다.
이 답변에서 지적된 n. 'pronouns' m.과 같이, C 표준은 부호가 있는 정수형의 음이 아닌 모든 값은 해당하는 부호가 없는 유형과 정확히 동일한 표현을 가지므로, 값이 두 유형의 범위에 있는 한 서로 교환하여 사용할 수 있다고 말합니다.
C99 표준 6.2.5 유형 - 제9항 및 각주 31:
9 부호화된 정수형의 음이 아닌 값의 범위는 해당 부호화되지 않은 정수형의 하위 범위이며, 각 유형에서 동일한 값의 표현은 동일. 31)
31) 동일한 표현 및 정렬 요건은 함수에 대한 인수, 함수로부터 가치를 반환하는 인수, 조합원으로서의 상호 교환성을 의미합니다.
정확히 동일한 내용은 C11 표준 6.2.5 유형 - 9항 및 각주 41에 있습니다.
이 표준의 저자들은 일반적으로 상상할 수 있는 모든 구석 사례에서 행동을 명시적으로 의무화하지는 않습니다. 특히 모든 구현의 100%가 공유하는 명백한 올바른 행동이 있을 때, 그리고 구현이 다른 작업을 수행하기를 기대할 이유가 없을 때 말입니다.서명된 형식과 서명되지 않은 형식은 둘 다에 맞는 값에 대해 일치하는 메모리 표현을 갖는다는 표준의 명시적인 요구 사항에도 불구하고, 이론적으로 구현이 그것들을 다양한 함수에 다르게 전달하는 것은 가능할 것입니다.표준은 그러한 행위를 금지하고 있지 않지만, 필자는 저자들이 의도적으로 그것을 허락했다는 증거가 없다고 봅니다.대부분의 경우, 구현이 그런 방식으로 작동한 적이 없었기 때문에 이러한 가능성을 고려하지 않았을 것입니다.
코드가 부호화된 값에 %x를 사용하는 경우 검사 구현이 스퀴크하는 것이 합리적일 수도 있지만 품질 검사 구현은 이러한 코드를 자동으로 수락하는 옵션도 제공해야 합니다.진단/위생 모드에서 사용되는 경우 제정신의 구현이 전달된 값을 서명되지 않은 값으로 처리하거나 스쿼크로 처리하는 것 외에 다른 작업을 수행할 이유가 없습니다.이 표준은 서명된 값에 %x를 사용하는 코드에 구현이 도달할 수 없는 것으로 간주하는 것을 금지할 수 있지만, 구현이 이러한 자유를 이용해야 한다고 생각하는 사람은 바보로 인정되어야 합니다.
오직 정상적인 비진단 구현을 목표로 하는 프로그래머들은 "uint8_t" 값과 같은 것들을 출력할 때 캐스트를 추가하는 것에 대해 걱정할 필요가 없지만, 바보 같은 구현에 코드가 입력되는 사람들은 그러한 구현이 강요할 수 있는 "최적화"로부터 컴파일러를 방지하기 위해 그러한 캐스트를 추가하기를 원할 수 있습니다.
언급URL : https://stackoverflow.com/questions/4664100/does-printfx-1-invoke-undefined-behavior
'code' 카테고리의 다른 글
활성 레코드:: 접속TimeoutError: 5.000초(대기 5.000초) 내에 데이터베이스 연결을 가져올 수 없습니다. (0) | 2023.09.20 |
---|---|
Oracle INSERT를 하나의 쿼리로 두 개의 테이블에 입력 (0) | 2023.09.20 |
특정 WooCommerce 이메일 알림에 대한 보낸 사람 이름 및 이메일 주소 변경 (0) | 2023.09.15 |
함수의 VLA 배열 매개 변수에 정수 대신 별표([*])를 사용하는 이유는 무엇입니까? (0) | 2023.09.15 |
mysql WHERE 절에서 "IN"의 값을 동적으로 추가하는 방법은? (0) | 2023.09.15 |