구조체 패딩 현상은 무엇일까?
성능 향상을 위해 CPU가 접근하기 쉬운 메모리에 구조체 필드를 배치하는 것이다.
예를 들어 그림1과 같이 구조체가 선언되었다면 해당 구조체의 크기는 9byte가 나올 것 같지만 실제로는 16byte가 나온다.
그 이유는 CPU가 접근하기 쉽게 구조체에 패딩 값을 넣어주는 구조체 패딩 현상이 일어났기 때문이다.
구조체 패딩 현상은 왜 일어날까?
64bit 운영체제일 때 CPU는 8byte씩 메모리를 읽어온다.
따라서 64bit 운영체제에서 그림1 구조체의 ll을 읽어오기 위해서는 그림2처럼 2번의 접근이 필요하다.
이런 경우 CPU가 접근하기 쉽게 구조체에 패딩 값을 그림3처럼 넣어주게 되는데 패딩 비트 크기만큼 메모리를 낭비하게 되지만 CPU가 그림1 구조체의 ll을 읽어올 때 메모리에 접근하는 횟수가 2번에서 1번으로 줄어들어 CPU의 연산 횟수가 감소한다.
즉, 구조체 패딩 현상은 CPU 연산 횟수를 줄여서 성능을 향상시킨다.
구조체 패딩 현상으로 생기는 문제점
네트워크를 통해 구조체를 전송하게 된다면 패딩 비트가 문제가 될 수 있다.
구조체가 메모리에 정의되는 형태는 OS와 컴파일러에 따라 다르다.
즉, 컴파일러에 따라 패딩 비트의 삽입 위치가 다르고, OS의 bit 수에 따라 삽입하는 패딩 비트의 수가 다르다.
따라서 서로 다른 메모리 정의를 가진 시스템 간 구조체를 주고 받는다면 패딩 비트로 인해 구조체의 값이 달라질 수 있다.
구조체 패딩 현상으로 생기는 문제점을 막기 위한 해결책은 무엇인가?
#pragma pack(push, 1)를 선언하면 된다.
위의 명령어는 1byte(두 번째 인자 값)단위로 저장하겠다는 뜻이다.
즉, 구조체 패딩현상을 막아서 운영체제나 컴파일러에 상관없이 구조체의 크기를 동일하게 만들 수 있다.
그렇다면 왜 모두 1byte로 해서 메모리의 낭비가 없도록 하지 않을까?
그 이유는 64bit CPU에서는 8byte의 단위로 데이터를 처리하는 것이 가장 빠르기 때문이다.
#pragma pack(push, 1) 이라고 선언하고 되돌리지 않으면 속도저하의 문제가 생길 수 있다.
따라서 64bit CPU에서는 구조체 선언이 끝나는 부분에 #pragma pack(push, 8) 이라고 선언해줘야 한다.
하지만 여기에도 문제가 있다.
만약 이 소스를 64bit의 PC가 아닌 8bit 또는 16bit의 CPU가 장착된 장비에서 컴파일 하게 된다면 소스를 하나씩 찾아서 CPU에 맞게 고쳐주고 다시 컴파일 해야 하는 불편함이 생긴다.
따라서 이런 문제를 해결하기 위해 #pragma pack(pop) 명령어를 사용한다.
그림4는 그림1 구조체 선언에서 발생하는 문제를 해결한 것이다.
구조체 전에 #pragma pack(push, 1)을 선언하여 구조체의 크기를 운영체제나 컴파일러에 상관없이 동일하게 하였고, 마지막에 #pragma pack(pop)을 사용하여 원래의 운영체제나 컴파일러에서 처리하는 byte 단위로 pop해주는 코드이다.
이렇게 하면 구조체의 크기는 어떤 CPU에서든 동일하게 가져가되 이후 소스 코드에서 데이터를 처리하는 단위는 해당 CPU의 운영체제나 컴파일러에 맞게 처리된다.
<참고 자료>
https://bumukisbest.tistory.com/18
'프로그래밍 언어 개념 > C' 카테고리의 다른 글
[C언어] 함수의 정의 (0) | 2023.11.23 |
---|---|
[C언어] Strcpy 함수 주의할 점 (0) | 2022.10.04 |
[C언어] static 변수 (0) | 2021.12.26 |
[C언어] 지역변수와 전역변수 (0) | 2021.12.23 |