size_t vs. uintptr_t
C 규격은 다음을 보증합니다.size_t
는 임의의 배열 인덱스를 유지할 수 있는 유형입니다.이것은 논리적으로,size_t
는 임의의 포인터 타입을 유지할 수 있어야 합니다.구글에서 찾은 일부 사이트에서 이 방법은 합법적이거나 항상 작동해야 한다고 읽은 적이 있습니다.
void *v = malloc(10);
size_t s = (size_t) v;
그 후 C99에서 표준이 도입되었습니다.intptr_t
그리고.uintptr_t
types: 포인터를 유지할 수 있는 것이 보증되는 부호 있는 타입과 부호 없는 타입입니다.
uintptr_t p = (size_t) v;
그럼 이 기능을 사용하는 것과는 어떤 차이가 있을까요?size_t
그리고.uintptr_t
둘 다 부호 없이 모든 포인터 유형을 유지할 수 있어야 하므로 기능적으로 동일한 것처럼 보입니다.이 제품을 사용해야 하는 진짜 설득력 있는 이유가 있습니까?uintptr_t
(더 좋은 것은,void *
)가 아닌size_t
명확성 말고?내부 기능만으로 필드를 처리하는 불투명한 구조에서 이렇게 하지 않을 이유가 있습니까?
같은 이유로,ptrdiff_t
포인터 차이를 유지할 수 있는 부호 있는 타입이며, 따라서 대부분의 포인터를 유지할 수 있습니다.그래서 어떻게 그것이 와 구별되는가?intptr_t
?
이 모든 타입은 기본적으로 동일한 기능의 3가지 버전을 제공하지 않습니까?만약 아니라면, 왜?둘 중 하나는 할 수 없고 다른 하나는 할 수 없는 게 뭐야?만약 그렇다면, 왜 C99는 기본적으로 불필요한 두 가지 유형을 언어에 추가했을까요?
현재의 문제에는 해당되지 않기 때문에 기능 포인터는 무시해도 되지만, 「정답」의 중심이 되지 않을까 하는 은근히 의심하고 있기 때문에, 자유롭게 언급할 수 있습니다.
size_t
는 임의의 배열 인덱스를 유지할 수 있는 유형입니다.즉, 논리적으로 size_t는 임의의 포인터 타입을 유지할 수 있어야 합니다.
꼭 그렇진 않아요!세그먼트화된 16비트 아키텍처의 시대로 거슬러 올라가 봅시다.예를 들어 어레이는 1개의 세그먼트(그래서 16비트)로 제한될 수 있습니다.size_t
하지만 여러 세그먼트를 가질 수 있습니다(32비트).intptr_t
세그먼트 및 세그먼트 내의 오프셋을 선택하려면 유형이 필요합니다).오늘날과 같이 세그먼트화되지 않은 아키텍처에서는 이상하게 들릴 수 있지만, 표준이 '2009년의 정상'보다 더 다양한 것을 충족시켜야 합니다.-)
세그먼트 제한, 이국적인 아키텍처 등에 대한 논리에 대해서는 다른 모든 답변에 대해 설명하겠습니다.
간단한 이름의 차이만으로도 적절한 활자를 사용할 수 있지 않을까요?
사이즈를 보존하는 경우는,size_t
포인터를 저장하는 경우,intptr_t
코드를 읽는 사람은 즉시 "아하, 이것은 어떤 크기입니다. 아마도 바이트 단위일 것입니다." 및 "아, 어떤 이유로든 포인터 값이 정수로 저장되어 있습니다."를 알 수 있습니다.
그렇지 않으면, 그냥 사용하실 수 있습니다.unsigned long
(혹은, 이 근대에 있어서,unsigned long long
)의 모든 것을 확인합니다.크기가 전부가 아닙니다. 활자 이름에는 프로그램을 설명하는 데 도움이 되기 때문에 유용한 의미가 있습니다.
귀하의 진술에 대해:
"C 표준은 다음을 보증합니다.
size_t
는 임의의 배열 인덱스를 유지할 수 있는 유형입니다.이것은 논리적으로,size_t
이렇게 하다'는 거예요.
이것은 사실 오류입니다(잘못된 (a)추리에서 비롯된 오해).당신은 후자가 전자와 일치한다고 생각할 수 있지만 사실은 그렇지 않다.
포인터와 배열 인덱스는 동일하지 않습니다.어레이를 65536개의 요소로 제한하지만 포인터가 128비트의 방대한 주소 공간에 어떤 값도 처리할 수 있는 적합한 구현을 상정하는 것은 매우 타당합니다.
는 C99의 .size_t
, 하다, 하다, 하다로 됩니다.SIZE_MAX
, 없음 참조).65535는 C99 TR3, 7.18.3, C11의변경 없음).현대 시스템에서 포인터가 이 범위로 제한된다면 포인터는 상당히 제한될 것입니다.
실제로, 여러분은 아마도 여러분의 가정이 타당하다는 것을 알게 될 것입니다. 하지만 그것은 표준이 그것을 보증하기 때문이 아닙니다.왜냐하면 그게 그걸 보장해주진 않거든요.
(a) 그나저나 이것은 인신공격의 어떤 형태가 아니라 비판적 사고의 맥락에서 당신의 진술이 왜 틀렸는지를 말하는 것이다.예를 들어 다음과 같은 추론도 유효하지 않습니다.
모든 강아지들은 귀엽다.이거 귀엽다.그러므로 이것은 강아지임에 틀림없다.
꼭두각시의 귀여움이나 다른 점은 여기에 관계가 없습니다.제가 말하고 싶은 것은 두 가지 사실이 결론으로 이어지지 않는다는 것입니다.첫 번째 두 문장은 강아지가 아닌 귀여운 것이 존재할 수 있기 때문입니다.
이것은 첫 번째 진술과 비슷하지만 두 번째 진술은 필연적으로 의무적이지 않습니다.
앞뒤를 모두 바라보며, 다양한 기묘한 건축물이 곳곳에 흩어져 있었던 것을 떠올려보면, 나는 그들이 모든 기존 시스템을 포장하고 모든 가능한 미래 시스템을 준비하려 했다고 확신한다.
확실히, 일이 해결되는 방식으로는, 지금까지 그렇게 많은 타입이 필요하지 않았다.
그러나 LP64에서도 시스템콜 인터페이스에 size_t와 ssize_t가 필요했습니다.64비트 타입의 풀 사용에는 비용이 많이 들고 4GB 이상의 I/O 처리에도 64비트 포인터를 사용할 수 있는 기존 시스템이나 미래의 시스템을 생각할 수 있습니다.
어떤 것이 개발되었을지, 미래에 어떤 일이 일어날지 궁금할 것입니다.(아마 128비트 분산 시스템 인터넷 전체의 포인터일 것입니다만, 시스템 콜의 64비트 이하이거나, 레거시 32비트 제한일 수도 있습니다.) 레거시 시스템에서 새로운 C 컴파일러를 얻을 수 있는 이미지...
또한, 그 주변에 무엇이 존재했는지 보세요.zillion 286 Real-Mode 메모리 모델 외에 CDC 60비트 워드/18비트 포인터 메인프레임은 어떻습니까?크레이 시리즈는 어때?통상의 ILP64, LP64, LLP64는 신경 쓰지 마세요.(저는 항상 Microsoft가 LLP64를 사용하는 것은 겉치레라고 생각했어요.위원회가 모든 기반을 커버하려고 하는 걸 상상할 수긍정적으로...
가장 큰 배열의 크기가 포인터보다 작을 수 있습니다.세그먼트 아키텍처에 대해 생각해 보십시오. 포인터는 32비트일 수 있지만, 단일 세그먼트는 64KB(예: 오래된 리얼 모드 8086 아키텍처)만을 처리할 수 있습니다.
데스크톱 머신에서는 더 이상 일반적으로 사용되지 않지만, C 표준은 소규모의 특수 아키텍처도 지원합니다.예를 들어 8비트 또는 16비트 CPU를 탑재한 임베디드 시스템이 아직 개발되고 있습니다.
(이것은 모든 타입의 이름에 해당) 당신의 의도를 코드로 전달하는 것이 더 낫다고 생각합니다.
를 들어, 「」라고 해도, 「」라고 해도,unsigned short
★★★★★★★★★★★★★★★★★」wchar_t
에서는 같은 (아마도)로 있습니다. 에서는 같은 사이즈로 되어 있습니다.wchar_t
unsigned short
는 임의의 숫자뿐만 아니라 와이드 문자를 저장하기 위해 사용하는 의도를 나타내고 있습니다.
int main(){
int a[4]={0,1,5,3};
int a0 = a[0];
int a1 = *(a+1);
int a2 = *(2+a);
int a3 = 3[a];
return a2;
}
즉, intr_t는 항상 size_t를 대체해야 하며 visa는 그 반대여야 합니다.
언급URL : https://stackoverflow.com/questions/1464174/size-t-vs-uintptr-t
'programing' 카테고리의 다른 글
변환 시 Vuex 상태가 업데이트되지 않음 (0) | 2022.07.04 |
---|---|
C++와 C의 조합 - #ifdef __cplus는 어떻게 동작합니까? (0) | 2022.07.04 |
vuex 스토어에서 특정 상태가 변경될 때 이벤트 발생 (0) | 2022.07.03 |
v-list 항목 vue + vuetify를 클릭하여 v-radio를 선택하는 방법 (0) | 2022.07.03 |
왜 무한 루프 상태가 되는 거죠? (0) | 2022.07.03 |