-목차-
1. 구조체 포인터 변수
2. 구조체 매개 변수 : "구조체 복사" vs "구조체 포인터"
3. 시간, 날짜와 관련된 C언어 표준 라이브러리 함수
1. 구조체 포인터 변수
※ 구조체 변수 값을 swap하는 함수 만들기
#include <stdio.h>
typedef struct student {
int id;
char *pname;
double points;
} STUD;
void stud_printx(STUD s) {
printf("[%d:%s] = %lf\n", s.id,s.pname,s.points);
}
void stud_swap(STUD s1, STUD s2) {
STUD tmp = s1;
s1 = s2;
s2 = tmp;
}
int main(void) {
STUD s1 = {1,"Kim",100};
STUD s2 = {2,"Hwang",98};
stud_printx(s1);
stud_printx(s2);
stud_swap(s1,s2);
stud_printx(s1);
stud_printx(s2);
return 0;
}
- 구조체 변수값을 swap하기 위해 stud_swap( ) 함수를 만들었다. 그러나 실행 결과 swap이 이루어지지 않았다!!
- swap이 되지 않은 이유는 Call by Value때문이다. 구조체 변수 역시 매개 변수로 값이 복사된다
※ 해결책??
- 구조체 자료형에도 포인터 사용 가능
- 구조체 포인터에서 구조체 멤버로 접근하기 위해 -> 연산자를 사용하자 ★★★★
#include <stdio.h>
typedef struct student {
int id;
char *pname;
double points;
} STUD;
void stud_printx(STUD* s) {
printf("[%d:%s] = %lf\n", s->id,s->pname,s->points);
}
void stud_swap(STUD* s1, STUD* s2) {
STUD tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
int main(void) {
STUD s1 = {1,"Kim",100};
STUD s2 = {2,"Hwang",98};
stud_printx(&s1);
stud_printx(&s2);
stud_swap(&s1,&s2);
stud_printx(&s1);
stud_printx(&s2);
return 0;
}
- stud_printx 함수의 매개 변수 인자를 STUD* s 로 설정함으로써 구조체 포인터 변수를 매개 변수로 설정하였다. ( 구조체 포인터 변수에 접근하기 위해서는 '->' 연산자를 사용해야 함!! )
- stud_swap 함수의 매개 변수 인자를 STUD* s1, STUD* s2로 설정하여 포인터 변수를 활용해 주소값에 접근하여 swap을 해주었다.
+) 주의할 점
- 연산자를 하나만 사용하여 구조체 포인터값에 접근하는것이 일반적이다.
- 두 개의 연산자 *,-> 를 사용할시 -> 연산자의 우선순위가 *연산자의 우선순위보다 높다
#include <stdio.h>
typedef struct student {
int id;
char *pname;
double points;
} STUD;
int main(void) {
STUD s1 = {1,"Kim",100};
STUD* ps1 = &s1;
s1.id = 2;
ps1->id = 3; // GOOD
(*ps1).id = 4; // OK
*ps1.id = 5; // Error
return 0;
}
2. 구조체 매개 변수 : "구조체 복사" vs "구조체 포인터"
※ 배열의 경우
- 대입 연산을 적용할 수 없고
- 함수 매개변수일 때 배열이 복사되는 것이 아니라 배열의 주소가 복사된다
※ 구조체의 경우
- 대입 연산을 적용할 수 있고
- 함수 매개변수일 때 값이 복사되는 것을 확인하였다
※ 구조체 복사, 즉 메모리 복사는 CPU의 효율을 떨어뜨리는 연산이다. 따라서 포인터 사용 추천!!
- 다만 함수 내에서 원하지 않는 구조체 내용 변경 등 Side Effect가 발생할 경우가 있다.
3. 시간, 날짜와 관련된 C언어 표준 라이브러리 함수
※ time_t time ( time_t *arg ) ;
- 1970년 1월 1일 자정을 기준으로 현재까지 흐른 시간을 초 단위로 계산하여 반환한다.
- param : 시간값이 저장될 포인터 변수 혹은 NULL 포인터
- return : 성공시 1970년 1월 1일부터 현재까지 흐른 시간을 초단위로 반환함. 실패시 -1 반환
+) T2K 문제와 비슷한 문제를 가지고 있다. (2038년이 되면 overflow가 발생함)
+) <time.h> 헤더파일에 typedef를 통해 정의되어 있음
ex)
#include <stdio.h>
#include <time.h>
int main(void) {
time_t tnow = time(NULL);
printf("The current thime is %ld seconds since the Epoch\n",tnow); // ld로 출력함을 잊지 말자
printf("sizeof(time_t) = %d\n",sizeof(time_t));
return 0;
}
※ struct tm* gmtime ( time_t* time ); ★★
- time*t time 매개변수값을 활용해 UTC로 바꿔줌.
- param : time_t 포인터 변수
- return : 성공시 구조체 tm의 포인터 변수를 반환, 실패시 NULL 포인터 변수 반환
#include <stdio.h>
#include <time.h>
int main(void) {
time_t tnow = time(NULL);
struct tm * pnow;
pnow = gmtime(&tnow);
if (pnow != NULL) {
printf("Today is %d.%d.%d and it\'s",
pnow->tm_year+1900, pnow->tm_month+1,pnow->tm_day);
switch(pnow->tm_wday) {
case 0 : puts("Sunday"); break;
case 1 : puts("Monday"); break;
case 2 : puts("Tuesday"); break;
case 3 : puts("Wednesday"); break;
case 4 : puts("Thursday"); break;
case 5 : puts("Friday"); break;
case 0 : puts("Saturday"); break;
}
}
return 0;
}
+) sturct tm -> time_t 로 돌리는 함수 : time_t mktime(struct tm* time);
※ char* asctime( struct tm* ptime );
- 주어진 struct tm* ptime 포인터 변수를 통해 요일 달 일 시간의 정보가 담긴 char 배열로 반환한다.
- param : sruct tm* ptime 포인터 변수
- return : 시간의 정보가 담긴 char 배열로 반환
※ struct tm * localtime( time_t *time ); ★★
- 주어진 struct tm* ptime 포인터 변수를 통해 현위치에서의 시간을 계산하여 반환함
- param : sruct tm* ptime 포인터 변수
- return : 현 위치의 시간의 정보가 담긴 포인터 변수를 반환
ex)
#include <stdio.h>
#include <time.h>
int main(void) {
time_t tnow = time(NULL);
struct tm * ptm_now;
//
ptm_now = gmtime(&tnow);
if (ptm_now) {
printf("Now in UTC : %s",asctime(ptm_now));
}
ptm_now = localtime(&tnow);
if (ptm_now) {
printf("Now in Local : %s",asctime(ptm_now));
}
//
time_t tepoch = 0,
ptm_now = gmtime(&tepoch);
if (ptm_now) {
printf("Now in UTC : %s",asctime(ptm_now));
}
ptm_now = localtime(&tnow);
if (ptm_now) {
printf("Now in Local : %s",asctime(ptm_now));
}
return 0;
}
+) 오늘 날짜, 오늘의 요일, 100일 이후의 날짜, 100일 이후의 요일를 출력하는 프로그램을 작성해보자
#include <stdio.h>
#include <time.h>
int main(void) {
time_t tnow = time(NULL);
struct tm *pnow;
// 오늘
pnow = gmtime(&tnow);
printf("오늘 날짜: %d.%d.%d 오늘 요일 : ",
pnow->tm_year+1900,pnow->tm_mon+1,pnow->tm_mday);
switch(pnow->tm_wday) {
case 0 : puts("Sunday"); break;
case 1 : puts("Monday"); break;
case 2 : puts("Tuesday"); break;
case 3 : puts("Wednesday"); break;
case 4 : puts("Thursday"); break;
case 5 : puts("Friday"); break;
case 6 : puts("Saturday"); break;
}
// 100일 이후
time_t tnow_100 = tnow + 60*60*24*100;
pnow = gmtime(&tnow_100);
printf("100일 후 날짜: %d.%d.%d 오늘 요일 : ",
pnow->tm_year+1900,pnow->tm_mon+1,pnow->tm_mday);
switch(pnow->tm_wday) {
case 0 : puts("Sunday"); break;
case 1 : puts("Monday"); break;
case 2 : puts("Tuesday"); break;
case 3 : puts("Wednesday"); break;
case 4 : puts("Thursday"); break;
case 5 : puts("Friday"); break;
case 6 : puts("Saturday"); break;
}
return 0;
}
'CS > C, C++' 카테고리의 다른 글
C/C++ 자료형 범위 및 바이트 (0) | 2024.04.19 |
---|---|
[C/C++] 09 - 1 구조체 기초 (0) | 2021.11.27 |
[C/C++] 08 - 2 배열, 문자열과 포인터 (0) | 2021.11.17 |
[C/C++] 08 - 1 포인터 개념 (0) | 2021.11.12 |
[C/C++] 07 - 3 함수와 모듈러 프로그래밍 (0) | 2021.11.02 |