programing

데이터 정렬이란 무엇입니까?C에 캐스팅 포인터를 입력할 때 왜 그리고 언제 걱정해야 합니까?

codeshow 2023. 10. 14. 10:46
반응형

데이터 정렬이란 무엇입니까?C에 캐스팅 포인터를 입력할 때 왜 그리고 언제 걱정해야 합니까?

정렬 시스템의 작동 방식과 일부 유형이 다른 유형보다 더 엄격하게 정렬되는 이유를 설명하는 괜찮은 문서를 찾을 수 없었습니다.

간단히 설명해 보겠습니다.

데이터 정렬이란 무엇입니까?

컴퓨터의 아키텍처는 프로세서와 메모리로 구성되어 있습니다.메모리는 셀로 구성되므로 다음과 같습니다.

 0x00 |   data  |  
 0x01 |   ...   |
 0x02 |   ...   |

각 메모리 셀은 지정된 크기와 저장할 수 있는 비트의 양을 가집니다.이는 아키텍처에 따라 달라집니다.

C/C++ 프로그램에서 변수를 정의하면 하나 이상의 다른 셀이 프로그램에 의해 점유됩니다.

예를들면

int variable = 12;

의 셀이 하고 하고를 한다고 가정하자,int유형 크기는 32비트이며 메모리의 어딘가에 있습니다.

variable: | 0 0 0 c |  // c is hexadecimal of 12.

CPU가 해당 변수에서 작동해야 할 때는 해당 변수를 레지스터 내부로 가져와야 합니다.CPU는 메모리에서 적은 양의 비트를 "1 클럭"으로 가져올 수 있으며, 그 크기를 보통 WORD라고 합니다.이 차원도 아키텍처에 따라 달라집니다.

이제 오프셋 때문에 두 개의 셀에 저장되는 변수가 있다고 가정합니다.

예를 들어, 저장해야 할 데이터가 두 개 있습니다("문자열 표현"을 사용하여 보다 명확하게 설명하려고 합니다).

data1: "ab"
data2: "cdef"

따라서 메모리는 다음과 같은 방식으로 구성됩니다(2개의 서로 다른 셀).

|a b c d|     |e f 0 0|

은,data1data2는 나머지 부분과 두번째 셀의 부분을 차지합니다.

가 CPU 합니다를 합니다.data2. CPU는 데이터에 액세스하기 위해 두 의 클럭이 필요한데, 한 클럭 내에 첫 번째 셀을 읽고 다른 클럭 내에 두 번째 셀의 나머지 부분을 읽기 때문입니다.

우리가 맞추면 data2이 기억-example에 따라서, 우리는 일종의 패딩과 시프트를 도입할 수 있습니다.data2두번째 감방에 다 있습니다.

|a b 0 0|     |c d e f|
     ---
   padding

그런 방식으로 CPU는 에 액세스하기 위해 "1 클럭"만 손실합니다.data2.

정렬 시스템이 수행하는 작업

얼라인 시스템은 아키텍처에 따라 데이터를 시스템의 메모리와 정렬하기 위해 그 패딩을 도입할 뿐입니다.

정렬에 신경을 써야 하는 이유는 무엇입니까?

저는 이 대답에 깊이 들어가지 않겠습니다.그러나 대체로 메모리 정렬은 컨텍스트의 요구 사항에서 비롯됩니다.

위의 예에서 패딩(따라서 데이터가 메모리 정렬됨)을 사용하면 데이터를 검색하기 위해 CPU 사이클을 절약할 수 있습니다.메모리 액세스 횟수가 적기 때문에 프로그램의 실행 성능에 영향을 줄 수 있습니다.

그러나 위의 예를 넘어(설명을 위해서만 만들어진) 메모리 정렬이 유용하거나 심지어 필요한 다른 시나리오도 많이 있습니다.

예를 들어, 일부 아키텍처에는 메모리에 액세스하는 방법에 대한 엄격한 요구 사항이 있을 수 있습니다.이러한 경우 패딩은 플랫폼 제약 조건을 충족하는 메모리를 할당하는 데 도움이 됩니다.

이는 "구현 정의된 구현"입니다. 즉, 정렬 요구 사항은 언어 사양의 일부가 아닙니다.

CPU마다 정렬에 대한 요구 사항이 다릅니다.어떤 것은 고르지 않은 주소에서 16비트 값을 처리할 수 없었고, 어떤 것은 그렇게 할 수 있었습니다.크기로 구분되는 주소에 정렬하지 않으면 부동 소수점 값을 지정할 수 없는 경우도 있었습니다.뭐 이런 거.잘못 정렬된 데이터 개체에 제대로 정렬된 개체보다 더 느리게 액세스하는 경우도 있고, 정렬되지 않은 개체에 액세스하는 경우도 있습니다.

그렇기 때문에 언어 표준은 어떤 유형이 어느 방향으로 정렬되어야 하는지에 대한 세부 사항으로 들어가지 않고 (그러지 못했기 때문에) "구현"(이 경우 컴파일러 백엔드)에 맡깁니다.

캐스트 포인터를 입력하면 지정된 개체를 주소 지정할 수 없는 주소로 지정하도록 코드를 강제할 수 있습니다."구" 유형의 정렬 요구 사항이 "신" 유형의 정렬 요구 사항만큼 엄격한지 확인해야 합니다.

C++(C++11 위쪽)에서는 연산자 정렬을 통해 지정된 유형의 정렬 요구 사항을 알 수 있습니다.또한 선형 연산자가 지정된 유형 또는 객체에 대해 보다 엄격한 선형을 적용하도록 할 수도 있습니다.

C(C11 위쪽)에서는 _Align of_Alignas 연산자를 얻을 수 있습니다.<stdalign.h>alignof/alignas 편의 매크로(고맙습니다, 런딘 -- C11은 제 장점이 아닙니다.)

일부 시스템은 32비트 워드(4바이트) 부분의 메모리에 액세스할 수 있습니다.하드웨어 제한입니다.즉, 메모리 컨트롤러에 들어가는 실제 주소를 4로 분할할 수 있어야 합니다(아직 바이트를 다루고 있기 때문입니다).그래서 일단 네 개로 나눌 수 없는 주소에 단어를 위치시키려고 하면, 두 가지 옵션이 있습니다. 컴파일러가 두 개의 메모리 액세스 중에서 그 단어를 구성하기 위해 멋진 코드를 생성하려고 시도하겠지만, 항상 그렇지는 않습니다.때로는 주어진 주소 중 4바이트에 접근하기 위한 코드를 생성하기도 합니다.그러면 데이터 정렬 오류로 인해 프로세서에 장애가 발생합니다.

그래서 언어가 제한을 받게 됩니다.

코드(나쁜 코드)를 생각해 보십시오.

uint8_t a[] = {1,2,3,4,5,6};
uint32_t b = *(uint32_t*)&a[1];

가정하고,a가 4개의 경계로 나눗셈에 정렬됩니다.그런 다음 두 번째 줄은 두 번째 요소의 주소, 즉 4로 분할되지 않는 주소에서 단어를 읽으려고 합니다.이는 정렬 오류로 이어집니다.하지만.C그것은 단지 엄격한 별칭 규칙에 의해서 금지됩니다.

언급URL : https://stackoverflow.com/questions/38875369/what-is-data-alignment-why-and-when-should-i-be-worried-when-typecasting-pointe

반응형