typedef struct {
uint16_t sec;
uint16_t min;
uint16_t hour;
} TIME_TypeDef;
TIME_TypeDef time;
//variable with position_t type. 4 Bytes are allocated in RAM
time.hour=18;
time.min=20;
time.sec=01;
// Also, we can define pointers to structures
TIME_TypeDef *pTime;
pTime=&time;
pTime->hour=17;
Example 2
struct Data {
char c1;
int *numPtr; // 포인터
};
int main()
{
int num1 = 10;
struct Data d1; // 구조체 변수
struct Data *d2 = malloc(sizeof(struct Data));
// 구조체 포인터에 메모리 할당
d1.numPtr = &num1;
d2->numPtr = &num1;
구조체 변수 d1의 멤버 numPtr을 역참조 하는 방법과 구조체 포인터 d2의 멤버 numPtr을 역참조 하는 방법을 그림으로 표현하면 다음과 같은 모양이 됩니다.
구조체 멤버가 포인터일 때 역참조하기
만약 역참조한 것을 괄호로 묶으면 어떻게 될까요? 이렇게 하면 구조체 변수를 역참조한 뒤 멤버에 접근한다는 뜻이 됩니다. *(*d2).numPtr처럼 구조체 포인터를 역참조하여 numPtr에 접근한 뒤 다시 역참조할 수도 있습니다.
(*구조체포인터).멤버
*(*구조체포인터).멤버
d2->c1 = 'a';
printf("%c\n", (*d2).c1); // a: 구조체 포인터를 역참조하여 c1에 접근
// d2->c1과 같음
printf("%d\n", *(*d2).numPtr); // 10: 구조체 포인터를 역참조하여 numPtr에 접근한 뒤 다시 역참조
// *d2->numPtr과 같음
여기서
(*d2).c1 는 d2->c1 같고
*(*d2).numPtr 는 *d2->numPtr 과 같습니다.
즉, 구조체 포인터를 역참조한 뒤 괄호로 묶으면 -> 연산자에서 . 연산자를 사용하게 되므로 포인터가 일반 변수로 바뀐다는 뜻입니다. 역참조의 원리와 같죠.
Example 3
구조체 별칭으로 선언한 포인터도 구조체 멤버에 접근할 때는 -> (화살표 연산자)를 사용합니다. p1->age = 30;
struct 키워드로 포인터를 선언하고 메모리를 할당했으니 typedef로 정의한 구조체 별칭으로도 포인터를 선언하고 메모리를 할당할 수 있겠죠?
구조체별칭 *포인터이름 = malloc(sizeof(구조체별칭));
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
typedef struct { // 구조체 이름이 없는 익명 구조체
char name[20]; // 구조체 멤버 1
int age; // 구조체 멤버 2
char address[100]; // 구조체 멤버 3
} Person; // typedef를 사용하여 구조체 별칭을 Person으로 정의
int main()
{
Person *p1 = malloc(sizeof(Person)); // 구조체 별칭으로 포인터 선언, 메모리 할당
// 화살표 연산자로 구조체 멤버에 접근하여 값 할당
strcpy(p1->name, "홍길동");
p1->age = 30;
strcpy(p1->address, "서울시 용산구 한남동");
// 화살표 연산자로 구조체 멤버에 접근하여 값 출력
printf("이름: %s\n", p1->name); // 홍길동
printf("나이: %d\n", p1->age); // 30
printf("주소: %s\n", p1->address); // 서울시 용산구 한남동
free(p1); // 동적 메모리 해제
return 0;
}
Example 4
지금까지 malloc 함수로 구조체 포인터에 동적 메모리를 할당했습니다. 그럼 동적 메모리를 할당하지 않고 구조체 포인터를 사용하는 방법은 없을까요? 이때는 구조체 변수에 & (주소 연산자)를 사용하면 됩니다.
구조체포인터 = &구조체변수;
#include <stdio.h>
struct Person { // 구조체 정의
char name[20]; // 구조체 멤버 1
int age; // 구조체 멤버 2
char address[100]; // 구조체 멤버 3
};
int main()
{
struct Person p1; // 구조체 변수 선언
struct Person *ptr; // 구조체 포인터 선언
ptr = &p1; // p1의 메모리 주소를 구하여 ptr에 할당
// 화살표 연산자로 구조체 멤버에 접근하여 값 할당
ptr->age = 30;
printf("나이: %d\n", p1.age);
// 나이: 30: 구조체 변수의 멤버 값 출력
printf("나이: %d\n", ptr->age);
// 나이: 30: 구조체 포인터의 멤버 값 출력
return 0;
}
ptr에 p1의 메모리 주소를 할당했으므로 ptr의 멤버를 수정하면 결국 p1의 멤버도 바뀝니다. 접근하는 방식만 차이가 있을 뿐 결국 같은 곳의 내용을 수정하게 됩니다(메모리 주소는 컴퓨터마다, 실행할 때마다 달라집니다).
구조체 변수의 주소와 구조체 포인터
Example 5: Structure in a Structure
Structure within Structure is a Useful technique for embedded programming (especially using FSM)
struct State{
uint8_t Out
uint8_t Time;
const struct State *Next[2];
};
typedef cost struct State State_t ;
State_t FSM[4]={
{0x21, 3000, {&FSM[0], &FSM[1] }}
{0x22, 500, {&FSM[1], &FSM[1] }}
};
Members: char building_name[100], int room_number, char room_name[100];
C_structure_exercise2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _CRT_SECURE_NO_WARNINGS
typedef struct {
char building_name[100];
int room_number;
char room_name[100];
} Handong;
int main()
{
// Create structure type (Handong) variable room1
Handong room1;
// Create structure type (Handong) variable room2, room3
// Your code goes here
// Create structure type (Handong) Pointer , roomPt
Handong *room1Pt = &room1;
// Assign room3 address to roomPt
// Your code goes here
// Define structure variable memeber values: room1
strcpy(room1.building_name, "Newton");
room1.room_number = 109;
strcpy(room1.room_name, "iiLAB");
// Define structure variable memeber values: room2
// Your code goes here
// Your code goes here
// Your code goes here
// Define structure variable memeber values: room3
// Your code goes here
// Your code goes here
// Your code goes here
// Print each member values : room1, room2, room3
printf("%s building, room %d is %s\n", room1.building_name, room1.room_number, room1.room_name);
// Your code goes here
// Your code goes here
// Print each member values by pointer variable: room1Pt
// Your code goes here
// Print address of room1 and value of room1Pt and compare.
printf("\n room1 address=%x , roomPt = %x \n", &room1, room1Pt);
}
Create structure variables room1, room2, room3. Assign the member values as