Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백준
- strlen()
- struct
- fork
- 구조체
- 자식
- pack
- 정보처리기사
- fwrite()
- signal
- Wait
- fgets()
- Kafka
- ifdef
- half-close
- 에라토스테네스의 체
- handling
- container
- 10989
- fread()
- 필기
- Docker
- DEBUG
- EOF
- sizeof()
- endif
- scanf()
- 카운팅 정렬
- 1929
- 2025
Archives
- Today
- Total
팥빵 먹으면서 코딩하는 블로그
05-2. [Linux/Ubuntu] 네트워크 프로그래밍 - 구조체 정렬 및 조건부 컴파일 옵션 본문
study/NETWORK PROGRAMMING
05-2. [Linux/Ubuntu] 네트워크 프로그래밍 - 구조체 정렬 및 조건부 컴파일 옵션
김팥빵_ 2025. 4. 4. 16:59구조체 정렬
- 이기종 시스템간 데이터 송수신
- 구조체 정렬 방식
- 구조체 내부에서 가장 큰 데이터 타입의 배수로 필드를 정렬
- 이렇게 되면 메모리 낭비 및 네트워크 대역폭 손실을 초래한다.
- Zero padding: 0으로 채워진 데이터(낭비된 데이터)
- 하지만 변수의 위치를 바꿈으로써 padding값을 줄일 수 있다.
- 구조체 변수들의 가장 위에서부터 내려가며 변수의 maximum byte값을 적용한다.
- 따라서 변수의 작은 값부터 큰 값까지 정렬하여 변수의 위치를 정하는 게 가장 효율적이다.
구조체 정렬 방법: #pragma pack
- pack 지시자
- 코드 상에서 pack 이후에 위치한 구조체의 정렬 방식을 지정한다.
- 한마디로, 구조제의 바이트 정렬 값을 지정
- #pragma pack(push, 정렬 바이트수)
- 정렬 바이트 수로 구조체를 정렬함(1, 2, 4, 8, 16)
- 1바이트를 쓰는 게 가장 효율적
- #pragma pack(push, 1) -> 1 byte 단위로 구조체를 정렬하겠다는 뜻
- #pragma pack(pop)
- 정렬 설정을 이전 상태(기본값)로 되돌림
- 양방향 통신에서 구조체를 똑같이 위치한다면 size가 같으므로 에러사항 없음
- 하지만 위치를 달리 했을 때는 통신 결과, 값이 충돌날 수 있음
- 따라서 pack 지시자를 적극 이용하는 게 필요함.
- 하지만 가장 중요한 건 코드간 서로 상호간 협의를 해놓는 게 중요!
- 참고) typedef로 바이트 수를 정의하는 법
- 서로 다른 구조체 정렬을 이용한 통신 결과
- server에는 pack을 사용(1 byte alignment)하고 client에는 pack을 쓰지 않은(no alignment) 경우
- client는 8바이트를 보냈지만, server는 1바이트 단위로 정렬해놨으므로 5바이트까지 수신한다.
- 따라서, 둘 다 정렬을 안 하거나, 둘 다 정렬을 하거나 해서 맞춰야 한다.
- 과거, 영국은 갤런단위, 미국은 그램단위로 연료량을 정했다가 연료가 과포함되어 로켓이 폭파한 사례
- server에는 pack을 사용(1 byte alignment)하고 client에는 pack을 쓰지 않은(no alignment) 경우
조건부 컴파일
Debug 정보 출력
- 계측 코드 내장 (instrumentation)
- C 전처리기 활용
- #defind DEBUF, #ifdef DEBUG ~ #else ~ #endif 등
- 선택적 컴파일
- 소스를 건들이지 않아도 컴파일 시점에 컴파일 옵션만 바꿔주면 됨
- !조건부 컴파일!
- -D<매크로이름> -o
- #ifdef DEBUG
- printf(“variable x has value = %d\n”, x);
- #endif
- 컴파일 방법
- $gcc 소스 파일.c –DDEBUG –o 실행파일이름
- 버그날 때, 저 조건을 넣어서 컴파일하면 디버깅할 수 있다.
- Debug용 매크로
- __LINE__ : 현재 행 번호를 표시
- __FILE__ : 현재 파일 이름을 뜻하는 문자열
- __DATE__ : 현재 날짜를 뜻하는 문자열 “mmm dd yyyy” 형태
- __TIME__ : 현재 시간(컴파일)을 뜻하는 문자열 “hh:mm:ss” 형태
- 빅엔디안, 리틀엔디안 디버깅
- 등등.
조건부 컴파일 예시
- #if ~ #endif
- #if ~ #elif ~ (#else) ~ #endif
- #if ~ #else ~ #endif
- #ifdef ~ #endif
- #if defined (조건1) && !defined (조건2)
- 여러 조건을 사용할 경우, defined를 사용함.
- #ifndef ~ #endif
- if not defined의 의미
- #error
- #error 출력 문자열
- 컴파일 과정에서 #error 부분이 컴파일되면 컴파일을 중지하고 오류 문자 출력
- 어느쪽에 정의가 되었는지 확인하기 위해 주로 사용한다.
#include <stdio.h>
#ifdef EN
#define HELLO_MESSAGE "Hello"
#elif defined KO
#define HELLO_MESSAGE "안녕하세요"
#elif defined FR
#define HELLO_MESSAGE "Bonjour"
#endif
int main() {
printf("%s\n", HELLO_MESSAGE);
return 0;
}
#include <stdio.h>
#ifdef _32BIT
typedef unsigned int uint32;
typedef int int32;
typedef unsigned long long uint64;
typedef long long int64;
#else
typedef unsigned int uint32;
typedef int int32;
typedef unsigned long uint64;
typedef long int64;
#endif
void main()
{
#if defined (LINUX) || defined (OSX)
printf("Unix machine\n");
#elif defined (WINDOWS) && defined(_32BIT)
printf("Windows machine 32bit\n");
printf(“sizeof(int64)=%ld\n”, sizeof(int64));
#elif defined (WINDOWS) && !defined(_32BIT)
printf("Windows machine 64bit\n");
#else
printf("Unknown machine\n");
#endif
}
- && 또는 || 으로 여러 조건을 같이 사용할 수 있음
'study > NETWORK PROGRAMMING' 카테고리의 다른 글
06-2. [Linux/Ubuntu] 네트워크 프로그래밍 - 도메인 이름과 인터넷 주소 (0) | 2025.04.11 |
---|---|
06-1 [Linux/Ubuntu] 네트워크 프로그래밍 - TCP 기반 Half-close (0) | 2025.04.11 |
05-1.[Linux/Ubuntu] 네트워크 프로그래밍 - UDP기반 서버/클라이언트 (0) | 2025.04.04 |
04-1. [Linux/Ubuntu] 네트워크 프로그래밍 - TCP 기반 서버/클라이언트 (0) | 2025.03.28 |
03-1. [Linux/Ubuntu] 네트워크 프로그래밍 - 소켓 타입과 프로토콜 설정 (0) | 2025.03.21 |