source

Memset(…, 0, …)을 여러 겹의 겹침에 사용하는 것이 합법입니까?

nicesource 2023. 10. 1. 19:32
반응형

Memset(…, 0, …)을 여러 겹의 겹침에 사용하는 것이 합법입니까?

입니까를 하여 복식입니까?memset(…, 0, …) 또는 복식 구조물?

이 질문은 두 가지 다른 것을 암시합니다.

  1. C 표준의 관점에서 보면:정의되지 않은 동작이 아닌가요? (특정 플랫폼에서는 정의되지 않은 동작이 될 수 없습니다. 부동 소수점 숫자의 메모리 내 표현에 의존하기 때문입니다.)

  2. 실제적인 관점에서:인텔 플랫폼에서는 괜찮은가요? (표준이 뭐라고 하든 상관없이)

C99 표준 부속서 F는 다음과 같이 말합니다.

이 부속서는 IEC 60559 부동 소수점 표준에 대한 C 언어 지원을 명시합니다. IEC 60559 부동 소수점 표준은 특히 마이크로프로세서 시스템을 위한 이진 부동 소수점 산술,2판(IEC 60559:1989), 이전에 지정된 IEC 559:1989IEEE 표준 for Binary 부동 소수점 산술(ANSI/IEEE 754-1985)입니다.IEEE Radix-Independent Floating-Point 산술 표준(ANSI/IEEE 854-1987)은 이진 표준을 일반화하여 Radix와 워드 길이에 대한 의존성을 제거합니다.IEC 60559는 일반적으로 IEC 60559 작동, IEC 60559 형식 등과 같이 부동 소수점 표준을 참조합니다.다음을 정의하는 구현.__STDC_IEC_559__이 부속문서의 규격을 준수해야 합니다.C 언어와 IEC 60559 간의 결합이 표시된 경우, 달리 명시되지 않는 한, IEC 60559-지정 동작은 참조에 의해 채택됩니다.

그리고 그 직후:

C 플로팅 유형은 다음과 같이 IEC 60559 형식과 일치합니다.

  • float형식은 IEC 60559 단일 형식과 일치합니다.
  • double형식은 IEC 60559 이중 형식과 일치합니다.

따라서 IEC 60559는 기본적으로 IEEE 754-1985이고, 이것은 8 0바이트가 0.0을 의미한다고 명시하기 때문에(@David Heffernan이 말한 것처럼) 정의된 것을 발견하면 0.0 초기화를 안전하게 수행할 수 있음을 의미합니다.

IEEE754를 말하는 경우 표준은 +0.0에서 두 배의 정밀도를 8 0바이트로 정의합니다.IEEE754 부동 소수점의 지원을 받는 것을 알고 있다면 이는 잘 정의된 것입니다.

인텔의 경우, 인텔 x86/x64에서 IEEE754를 사용하지 않는 컴파일러는 생각할 수 없습니다.

데이비드 헤퍼넌은 질문의 (2)부분에 대해 좋은 답변을 해주었습니다.(1)부의 경우:

C99 표준은 일반적인 경우에 부동 소수점 값의 표현에 대해 보장하지 않습니다.§6.2.6.1은 다음과 같이 말합니다.

모든 유형의 표현은 이 하위 조항에 명시된 것을 제외하고는 지정되지 않았습니다.

그리고 그 하위 조항은 부동 소수점에 대해서는 더 이상 언급하지 않습니다

당신이 말했잖습니까?

(고정 플랫폼에서 이 UB는 어떻게... 유동 표현에 의존할 수 있습니까?)

실제로 - "정의되지 않은 행위", "지정되지 않은 행위" 및 "구현 정의된 행위" 사이에는 차이가 있습니다.

  • "정의되지 않은 행동"이란 어떤 일이 일어날 수 있음을 의미합니다(시동 충돌 포함).
  • "특정되지 않은 행동"은 컴파일러가 원하는 방식으로 합리적인 것을 자유롭게 구현할 수 있지만, 구현 선택이 문서화될 필요는 없다는 것을 의미합니다.
  • "구현 정의된 동작"은 컴파일러가 원하는 방식으로 합리적인 것을 자유롭게 구현할 수 있다는 것을 의미하며, 그 선택을 문서화하도록 되어 있습니다(예를 들어, 가장 최근의 GCC 릴리스에서 문서화된 구현 선택 사항은 여기를 참조하십시오).

부동 소수점 표현은 특정되지 않은 동작이기 때문에 플랫폼마다 문서화되지 않은 방식으로 달라질 수 있습니다(여기서 "플랫폼"은 단순히 "hardware"가 아닌 "하드웨어와 컴파일러의 조합"을 의미합니다).

는 그 유용한지 잘 .) (.double - 0이가 0됩니다가 표시됩니다.+0.0한다면__STDC_IEC_559__마테오 이탈리아의 답변에서 설명한 바와 같이 정의되어 있으며, 실제로 실행되고 있습니다.예를 들어, 많은 하드웨어 플랫폼에서 IEEE 754 / IEC 60559를 사용하더라도 GCC는 이를 정의하지 않습니다.)

컴퓨터에 문제가 발생할 가능성은 낮지만, 질문 제목에서 언급한 대로 어레이에 대해 말하는 경우와 컴파일 시 길이가 알려진 경우(VLA가 아님)에는 비교적 쉽게 초기화할 수 있습니다.

double A[133] = { 0 };

항상 작동해야 합니다.나중에 그런 배열을 다시 0으로 만들어야 하고 컴파일러가 현대 C(C99)를 준수하는 경우 복합 리터럴을 사용하여 이 작업을 수행할 수 있습니다.

memcpy(A, (double const[133]){ 0 }, 133*sizeof(double));

이것은 어떤 현대의 컴파일러에 있어서 만큼 효율적이어야 합니다.memset, 그러나 특정 인코딩에 의존하지 않는 장점이 있습니다.double.

마테오 이탈리아 말대로 그건 기준에 따라 합법적이지만 저는 사용하지 않을 겁니다.뭐 이런 거.

double *p = V, *last = V + N;  // N is count
while (p != last) *(p++) = 0;

최소 2배 이상 빠릅니다.

사용하는 것은 "합법"입니다.memset. 문제는 이것이 비트 패턴을 생성하는지 여부입니다.array[x] == 0.0사실입니다.기본적인 C 표준은 그것이 사실일 것을 요구하지 않지만, 나는 그것이 사실이 아닌 예를 듣고 싶습니다!

0으로 설정한 것으로 보입니다.memset는 IBM-AIX, HP-UX(PARISC), HP-UX(IA-64), Linux(IA-64)에서 0.0을 할당하는 것과 같습니다.

간단한 테스트 코드는 다음과 같습니다.

double dFloat1 = 0.0;
double dFloat2 = 111111.1111111;

memset(&dFloat2, 0, sizeof(dFloat2));

if (dFloat1 == dFloat2) {
    fprintf(stdout, "memset appears to be equivalent to = 0.0\n");
} else {
    fprintf(stdout, "memset is NOT equivalent to = 0.0\n");
}

음, 저는 제로잉이 "합법적"이라고 생각하지만(결국은 일반 버퍼를 제로화하는 것입니다), 표준이 결과적인 논리적 가치에 대한 가정을 가능하게 하는지 모르겠습니다.제 추측으로는 C 표준은 정의되지 않은 상태로 남아 있을 것입니다.

언급URL : https://stackoverflow.com/questions/4629853/is-it-legal-to-use-memset-0-on-an-array-of-doubles

반응형