programing

When to use const void*?

sourcejob 2023. 10. 26. 20:58
반응형

When to use const void*?

이 간단한 테스트 기능을 가지고 있습니다. 이 기능을 사용하여 컴퓨터에 무슨 일이 일어나고 있는지 파악하고 있습니다.const한정자

int test(const int* dummy)
{
   *dummy = 1;
   return 0;
}

This one throws me an error with GCC 4.8.3. Yet this one compiles:

int test(const int* dummy)
{
   *(char*)dummy = 1;
   return 0;
}

그래서 뭔가.const한정자는 다른 유형에 캐스팅하지 않고 인수를 사용하는 경우에만 작동합니다.

Recently I've seen codes that used

test(const void* vpointer, ...)

적어도 내가 사용할 때는void *, 제가 캐스팅을 하는 편입니다.char스택에서 포인터 산술을 사용하거나 추적할 수 있습니다.어떻게 할수있을까요const void서브루틴 함수가 데이터를 수정하는 것을 방지합니다.vpointer포인팅인가요?

const int *var;

const계약입니다.A를 받음으로써const int *매개변수는 호출자에게 자신(호출 함수)이 포인터가 가리키는 개체를 수정하지 않을 것이라고 "말"합니다.

Your second example explicitly breaks that contract by casting away the const qualifier and then modifying the object pointed by the received pointer. Never ever do this.

이 "계약"은 컴파일러에 의해 실행됩니다.*dummy = 1컴파일되지 않습니다.출연진은 컴파일러에게 당신이 무엇을 하고 있는지를 정말로 알고 있고, 당신이 그것을 할 수 있도록 함으로써 그것을 우회할 수 있는 방법입니다.불행하게도 "내가 무엇을 하고 있는지 정말로 알고 있습니다"라는 말은 보통 그렇지 않습니다.

const컴파일러가 최적화를 수행하는 데 사용할 수도 있습니다.


Undefined Behavior note:

캐스트 자체는 기술적으로 합법적이지만, 다음과 같이 선언된 값을 수정하는 것은 주의하시기 바랍니다.constUndefined Behavior.따라서 기술적으로는 포인터가 변이 가능하다고 선언된 데이터를 가리키기만 하면 원래 기능은 괜찮습니다.그렇지 않으면 정의되지 않은 동작입니다.

more about this at the end of the post


동기부여와 사용에 관해서는 다음의 주장을 들어보겠습니다.strcpy그리고.memcpy함수:

char* strcpy( char* dest, const char* src );
void* memcpy( void* dest, const void* src, std::size_t count );

strcpy차끈으로 작동하고,memcpy일반 데이터에서 작동합니다.strcpy를 예로 들지만, 다음의 논의는 둘 다 정확히 동일하지만,char *그리고.const char *위해서strcpy그리고.void *그리고.const void *위해서memcpy:

destchar *왜냐하면 버퍼안에dest그 함수는 복사본을 넣을 것입니다.함수는 이 버퍼의 내용을 수정하므로 일정하지 않습니다.

srcconst char *왜냐하면 기능은 버퍼의 내용만 읽기 때문입니다.src. 수정되지 않습니다.

함수의 선언을 보아야만 발신자는 위의 모든 것을 주장할 수 있습니다.계약으로strcpy인수로 전달된 두 번째 버퍼의 내용을 수정하지 않습니다.


const그리고.void직교합니다.그것이 위의 논의의 전부입니다.const모든 유형에 적용됩니다(int,char,void, ...)

void *는 "일반적인" 데이터를 위해 C에서 사용됩니다.


정의되지 않은 동작에 대한 추가 정보:

사례 1:

int a = 24;
const int *cp_a = &a; // mutabale to const is perfectly legal. This is in effect
                      // a constant view (reference) into a mutable object

*(int *)cp_a = 10;    // Legal, because the object referenced (a)
                      // is declared as mutable

사례 2:

const int cb = 42;
const int *cp_cb = &cb;
*(int *)cp_cb = 10;    // Undefined Behavior.
                       // the write into a const object (cb here) is illegal.

저는 이 예시들이 이해하기 쉽기 때문에 이 예시들로 시작했습니다.여기서부터는 인수 기능을 수행하는 단계가 하나뿐입니다.

void foo(const int *cp) {
    *(int *)cp = 10;      // Legal in case 1. Undefined Behavior in case 2
}

사례 1:

int a = 0;
foo(&a);     // the write inside foo is legal

사례 2:

int const b = 0;
foo(&b);     // the write inside foo causes Undefined Behavior

다시 한 번 강조하겠습니다: 여러분이 정말로 무엇을 하고 있는지를 알지 못하고, 현재와 미래에 법전에 관련된 일을 하는 모든 사람들이 전문가이고 이것을 이해하지 못한다면, 여러분은 좋은 동기를 가지고 있고, 위의 모든 것이 충족되지 않는 한, 절대로 일관성을 버리지 마세요.

int test(const int* dummy)
{
   *(char*)dummy = 1;
   return 0;
}

아니요, 이거 안 돼요.(진정으로) 꾸준함을 버립니다.constdata)는 정의되지 않은 동작이며, 예를 들어 구현이 완료되면 프로그램이 충돌할 가능성이 높습니다.constROM의 데이터."그것이 작동한다"는 사실은 코드가 잘못되었다는 사실을 바꾸지 않습니다.

적어도 저는 void*를 사용할 때 스택에서 포인터 산술을 하거나 추적을 위해 char*에 캐스팅하는 편입니다.vpointer가 가리키는 데이터를 서브루틴 함수가 수정하지 못하도록 하려면 어떻게 해야 합니까?

A const void*변경할 수 없는 일부 데이터에 대한 포인터를 의미합니다.읽어보려면 네, 다음과 같은 구체적인 유형으로 던져야 합니다.char. 하지만 저는 이 아니라 읽기라고 말했는데, 그것은 역시 UB입니다.

이 부분은 여기서 좀 더 깊이 다루게 됩니다.C를 사용하면 유형 안전을 완전히 무시할 수 있습니다. 이를 방지하는 것이 여러분의 일입니다.

주어진 OS에 주어진 컴파일러가 자신의 일부를 넣을 수 있습니다.const읽기 전용 메모리 페이지의 데이터.이 경우 해당 위치에 기록을 시도하면 일반적인 보호 오류가 발생하는 등 하드웨어에서 실패합니다.

const한정자는 정의되지 않은 동작이 있다는 것을 의미합니다.이는 언어 표준을 사용하면 프로그램이 중단될 수 있음을 의미합니다.그럼에도 불구하고, C는 당신이 무엇을 하고 있는지 알고 있다고 생각되면 당신의 발에 총을 쏘게 해줍니다.

서브루틴이 원하는 비트를 원하는 대로 재해석하고 원하는 기계 명령을 실행하는 것을 막을 수 없습니다.전화하시는 라이브러리 함수는 어셈블러로 작성되어 있을 수도 있습니다.하지만 그렇게 하는 것은.const포인터는 정의되지 않은 동작이며, 정의되지 않은 동작을 호출하고 싶지 않을 것입니다.

이해가 되는 드문 예가 있습니다. 핸들 파라미터를 중심으로 전달되는 라이브러리가 있다고 가정해 보겠습니다.그것은 어떻게 그것들을 생성하고 사용합니까?내부적으로는 데이터 구조에 대한 지침일 수 있습니다.그래서 그것은 당신이 할 수 있는 애플리케이션입니다.typedef const void* my_handle;그래서 컴파일러는 만약 당신의 클라이언트들이 실수로 오류를 제거하거나 산술을 하려고 한다면 오류를 던지고, 당신의 라이브러리 함수 안에 있는 당신의 데이터 구조에 대한 포인터로 그것을 다시 던집니다.가장 안전한 구현은 아니며, 라이브러리에 임의의 값을 전달할 수 있는 공격자를 주의해야 하지만 이는 매우 낮은 오버헤드입니다.

언급URL : https://stackoverflow.com/questions/34842224/when-to-use-const-void

반응형