C 언어 구조체 포인터 배열 매개변수 - C eon-eo gujoche pointeo baeyeol maegaebyeonsu

-목차- 

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; }

Toplist

최신 우편물

태그