왜 float에 대한 지정자가 printf에 정의되지 않았는가?
그럴 수도 있었을 것 같은데, (적어도 C99에는) 길이 수식어가 적용 가능한 것 같다.int
:%hhd
%hd
%ld
그리고%lld
심술궂다signed char
short
long
그리고long long
에 적용되는 길이 수식어도 있다.double
:%Lf
수단long double
.
문제는 왜 그들이 누락했는가 하는 것이다.float
대로라면, 였을 이다.%hf
.
ISO C11 표로 ,로터,6.5.2.2 Function calls /6
그리고/7
, 표현식의 맥락에서 함수 호출에 대해 논함(나의 강조):
6/ 호출된 함수를 나타내는 식이 프로토타입을 포함하지 않는 유형을 갖는 경우, 각 인수에 정수 승진이 수행되며, 유형 부동이 있는 인수는 2배로 승격된다. 이를 기본 인수 프로모션이라고 한다.
7/ 호출된 함수를 나타내는 식에 프로토타입이 포함된 형식이 있는 경우, 각 매개변수의 유형을 선언된 형식의 부적격 버전으로 취하면서 해당 매개변수의 유형을 할당에 의해 암시적으로 변환한다.함수 프로토타입 선언기의 줄임표 표기법은 인수 유형 변환을 마지막으로 선언된 파라미터 이후에 중지하게 한다.기본 인수 승진은 후행 인수에서 수행된다.
이것은 어떤 것이든 라는 것을 의미한다.float
그 후의 논쟁....
에서는, 「로다」로한다.double
그리고printf
통화 패밀리는 그렇게 정의된다.7.21.6.11
et seq:
int fprintf(FILE * restrict stream, const char * restrict format, ...);
그러니까, 할 수 있는 방법이 없기 때문에.printf()
-가족이 실제로 부동액을 받으려고 전화하는 것, 그것에 대한 특별한 형식 지정자(또는 수식어)가 있다는 것은 말이 안 된다.
C 가 다양한 C가 가능하기 때문이다.float
논거가 a로 승격(즉, 변환)된다.double
그렇게printf
A을 얻고 있다.double
그리고 사용할 것이다.va_arg(arglist, double)
구현에 포함시킬 수 있을 겁니다.
, 에서는 매 과(C89, K&R C)이 모모이다.float
논쟁은 a로 전환되었다.double
현행 표준은 명시적 프로토타입이 있는 고정된 아리티 기능에 대해 이 프로모션을 생략한다.그것은 이 구현의 ABI & 호출 규약과 관련이 있다(그리고 세부사항은 설명되어 있다).현실적으로 말하면 afloat
인수로 전달될 때 값이 종종 이중 섀시 포인트 레지스터에 로드되지만 세부 사항은 다를 수 있다.예를 들어 Linux x86-64 ABI 규격을 읽어 보십시오.
또한, 특정 형식 제어 문자열을 제공할 실질적인 이유가 없다.float
출력 너비를 조정할 수 있기 때문에(예:%8.5f
) 원하는 대로, 그리고%hd
훨씬 더 유용하다(필요하다)scanf
에 있어서보다printf
그 너머로는 (누락해야 할) 이유가 있을 것 같다.%hf
지만 float
-에 대한 제한double
에 하여.printf
)은 역사적이다: 처음에 C는 HPC가 아니라 시스템 프로그래밍 언어였다(Fortran은 아마도 1990년대 후반까지 HPC에서 선호되었다).float
별로 중요하지 않았다; 그것은 (그리고 지금도) 같은 생각이었다.short
메모리 소비를 줄이는 방법.그리고 오늘날의 FPU는 (데스크톱 또는 서버 컴퓨터에서) 사용할 수 있을 만큼 빠름float
기억력을 줄이기 위한 수단일 뿐이지기본적으로 당신은 모든 사람이float
(아마도 FPU 또는 CPU 내부)로 변환된 위치double
.
사실, 당신의 질문은 다음과 같은 말로 표현될 수 있다: 왜%hd
을 위해 존재하다.printf
(근본적으로 쓸모없는 곳, 그 이후부터)printf
을 얻고 있다.int
조금면 면면 .short
그러나scanf
안 돼!) 더할 것 이유는 모르겠지만, 시스템 프로그래밍보다 더 유용할 것 같아.
은 C할 수 .%hf
에 의해 받아들여지다.printf
을 위해float
에)double
에서printf
전화 같은 것short
-s가 로 승진하다.int
)) 이중 정밀도 값이 범위를 벗어날 때 정의되지 않은 동작으로float
-s, thoughly symetrically.%hf
에 의해 받아들여지다.scanf
을 위해float
포인드. 을 빈다행운을 빌어요.
기본 인수 승급 때문에.
printf()
수능 인맥)이다....
그 서명으로), 모두float
논거가 로 승격되다.double
.
C11 §6.5.2.2 함수 호출
6 호출된 함수를 나타내는 식이 프로토타입을 포함하지 않는 유형을 갖는 경우, 각 인수와 유형이 있는 인수에 대해 정수 승진이 수행된다.
float
로 승진하다.double
이를 기본 인수 프로모션이라고 한다.7 함수 프로토타입 선언기의 줄임표 표기법은 인수 유형 변환을 마지막으로 선언된 매개변수 이후에 중지하게 한다.기본 인수 승진은 후행 인수에서 수행된다.
변수 함수를 호출할 때 기본 인수 프로모션으로 인해 값이 함수 호출 이전으로 암시적으로 변환되며 값을 전달할 방법이 없다.float
에 가치를 두다.printf
, 에 대한 명시적 형식 지정자가 필요 없음float
가치
그런 말을 한 앙투안엘은 다음과 같은 논평에서 흥미로운 점을 꺼냈다.%lf
(현재 에 사용됨scanf
인 에에 double *
)은 한때 "을 의미했을지도 모른다.long float
C99 이론의 42페이지에 따르면, C89일 이전의 동의어 형식이었다.그 논리로 보면, 이치에 맞을지도 모른다.%f
A을 지지하기 위한 것이었다.float
로 한 값double
.
에 관하여hh
그리고h
길이 한정자,%hhu
그리고%hu
다음 형식 지정자에 대해 잘 정의된 사용 사례를 제시하십시오.라지 중에서 가장 중요하지 않은 바이트를 인쇄할 수 있다.unsigned int
또는unsigned short
예를 들어, 깁스를 하지 않은 경우:
printf("%hhu\n", UINT_MAX); // This will print (unsigned char) UINT_MAX
printf("%hu\n", UINT_MAX); // This will print (unsigned short) UINT_MAX
로부터의 좁은 전환은 특별히 잘 정의되어 있지 않다.int
로char
또는short
결과적으로, 그러나 그것은 적어도 구현이 정의된다. 즉, 구현이 이 결정을 실제로 문서화하는 데 필요함을 의미한다.
패턴대로라면 그랬어야 했는데
%hf
.
당신이 관찰한 패턴을 따라%hf
다음 범위를 벗어나는 값을 변환해야 함float
로 돌아가다.float
하지만, 그런 종류의 변환은double
로float
정의되지 않은 행동을 하게 되고, 그런 행동은 없다.unsigned float
. 보이는 패턴은 말이 안 된다.
공식적으로 옳게 말하자면%lf
a를 나타내지 않는다.long double
그리고 만약 당신이 A를 통과한다면long double
정의되지 않은 행동을 유발할 수 있다는 주장문서에는 다음과 같은 내용이 명시되어 있다.
l
(엘) ...다음 사항에 영향을 미치지 않다.a
,A
,e
,E
,f
,F
,g
또는G
전환 지정자
아무도 이걸 알아채지 못했다니 놀랍군? %lf
a를 나타내다double
마치 논쟁처럼%f
. 인쇄하려면long double
, 사용%Lf
(자본 타원).
이제 와서는 이치에 맞다.%lf
양자를 위하여printf
그리고scanf
에 해당하다double
그리고double *
논쟁들... %f
앞에서 언급한 이유 때문에 기본 인수 프로모션 때문에만 예외적이다.
…과%Ld
는 뜻이 아니다long
어느 쪽이든그것이 의미하는 것은 정의되지 않은 행동이다.
Fscanf 아래의 C 논거를 읽어 보면 다음과 같은 것을 알 수 있다.
C99의 새로운 기능:hh 및 l 길이 한정자는 C99에 추가되었다. ll은 새로운 long int 유형을 지원한다.hh는 문자 유형을 다른 정수 유형과 동일하게 취급하는 기능을 추가한다. 이는 SCNd8 in과 같은 매크로를 구현하는 데 유용할 수 있다(7.18 참조).
그래서 아마도hh
새로운 모든 것에 대한 지원을 제공하기 위해 추가되었다.stdint.h
이것은 왜 작은 정수에는 길이 수식어가 추가되었지만 작은 부유물에는 추가되지 않았는지를 설명할 수 있다.
C90이 왜 일관성이 없었는지는 설명되지 않는다.h
그러나 아니다hh
그래도C90에 명시된 언어가 항상 일치하지는 않으며, 그렇게 간단하지 않다.그리고 이후 버전들은 모순을 물려받았다.
C가 발명되었을 때, 모든 부동 소수점 값은 공통 유형(즉, 공통 유형)으로 변환되었다.double
계산에 사용되거나 함수에 전달되기 전(포함)printf
, 그래서 그럴 필요가 없었다.printf
부동 소수점 유형 간에 구별할 수 있다.
산술 효율성과 정확성을 촉진하기 위해 IEEE-754 부동 소수점 표준은 일반 64비트보다 큰 80비트 유형을 정의했다.double
하지만 더 빨리 처리될 수 있다.그 의도는 다음과 같은 표정을 지으면서였다.a=b+c+d;
합계를 계산하는 것보다 모든 것을 80비트 유형으로 변환하고, 세 개의 80비트 숫자를 합산하고, 결과를 64비트 유형으로 변환하는 것이 더 빠르고 정확할 것이다.(b+c)
64비트 유형으로 지정한 다음d
.
새로운 유형을 지원하기 위해, ANSI C는 새로운 유형을 정의했다.long double
새로운 80비트 유형 또는 64비트를 참조할 수 있는 구현double
. 불행히도, IEEE-754 80비트 유형의 목적은 모든 값이 새로운 유형으로 자동 승격되도록 하는 것이었지만, 그들이 새로운 유형으로 승격된 방식이었다.double
, ANSI가 그것을 만들어 새로운 타입이 전달되도록 했다.printf
또는 다른 가변적 방법들이 다른 부동소수점 유형과 다르기 때문에 그러한 자동 승진이 불가능하게 된다.
따라서 C가 생성될 때 존재했던 두 부동소수점 유형은 동일한 값을 사용할 수 있다.%f
형식 지정자를 지정하지만long double
이후에 만들어진 것은 다른 것을 필요로 한다.%Lf
형식 지정자(대소문자 포함) L
).
%hhd
%hd
%ld
그리고%lld
에 추가되었다.printf
형식 문자열을 보다 일관적으로 만들기 위해scanf
에 대해 중복됨에도 불구하고printf
기본 인수 프로모션 때문에.
그럼 왜 안 그랬어?%hf
을 위해 추가된.float
쉽네, 보고 있자니scanf
의 행동,float
형식 지정자가 이미 있다.너무 좋다.%f
. 그리고 형식 지정자.double
이다%lf
.
저것%lf
C99가 정확히 C99에 추가한 것이다.printf
C99의 의 행동.%lf
정의되지 않았다(표준에서 정의가 누락됨).C99를 기준으로 하면 의 동의어다.%f
.
고려하다scanf
롱의 플로트, 더블이 롱 더블에 왜 플로트인지 printf
비슷한 기능들이 비슷한 방식으로 구현되지 않았지만, 그렇게 해서 C / C++와 표준이 완성되었다.
프로세서와 현재 모드에 따라 푸시 또는 팝 작업을 위한 최소 크기에 문제가 있을 수 있지만, 이것은 구조물의 로컬 변수나 변수의 기본 정렬과 유사한 기본 패딩으로 처리되었을 수 있다.Microsoft에서 80비트(10바이트)에 대한 지원을 중단함long double
s 16비트에서 32비트/64비트 컴파일러로, 이제 치료long double
double
(64비/8바) 그들은 필요에 또는 수 이것은 필요에 따라 12~16바이트 경계까지 패딩할 수도 있었지만, 이 작업은 이뤄지지 않았다.
참조URL: https://stackoverflow.com/questions/32517932/why-wasnt-a-specifier-for-float-defined-in-printf
'Programing' 카테고리의 다른 글
Java를 MySQL 데이터베이스에 연결 (0) | 2022.04.21 |
---|---|
Vue 및 Vuex: 상태를 변경할 때 계산된 속성이 호출되지 않음 (0) | 2022.04.20 |
Java에서 mod의 구문 (0) | 2022.04.20 |
Vue.js의 eslint에서 '구성 요소가 등록되었지만 사용되지 않음' 제거 (0) | 2022.04.20 |
장치 드라이버 쓰기를 어떻게 시작해야 하는가? (0) | 2022.04.20 |