__________

Designing the Future with Circuits

반도체 회로설계 취준기

하만(Harman) 세미콘 반도체 설계 과정/임베디드 시스템을 위한 SW 구조설계

하만(Harman) 세미콘 아카데미 5일차 - SW 구조설계(포인터 / 함수 포인터 / 자료형 / 구조체 / 공용체)

semicon_designer 2024. 3. 13. 11:06
728x90

[2024.03.13.수] 인천인력개발원 하만 세미콘 아카데미


임베디드 시스템을 위한 SW 구조설계


포인터


  • 포인터
    • 메모리의 주소 값을 저장하는 변수(=표인터 변수)
    • 컴퓨터의 주소 체계에 따라 크기 결정(32비트 시스템 -> 4바이트)
  • 포인터 타입&선언
    • 포인터 선언 시 연산자 * 사용
    • A형 포인터: A형 변수에 주소 값을 저장
  • 주소 관련 연산자
    • &연산자: 변수의 주소 값 반환
    • *연산자: 포인터가 가리키는 메모리 참조

포인터와 배열


  • 배열 이름: 첫 번째 요소의 주소값을 나타냄 => 배열 이름은 상수
  • 포인터 연산: 포인터의 값을 증감
    • 포인터가 가리키는 대상의 자료형에 따라 증감되는 값의 차이가 발생
    • 포인터 연산을 통한 배열 요소의 접근
      *b = a; //이면
      *(b+n) = a[n];​​​
      1. 배열 요소의 인덱스 변수로 접근
      2. 포인터를 통해 offset값으로 접근

 

결론: arr[i] == *(arr+i)

  • 포인터 배열: 포인터가 배열의 요소가 되는 배열
    • int* arr1[10];
      double* arr2[20];
      char* arr3[30]; => 문자열 배열( char* arr3[30] = {"program", "code", "~~", ...}) 에서 각 문자열이 할당된 메모리의 주소를 저장하는 배열
    • 문자열은 각 요소별로 1000(16)의 메모리를 할당(문자열은 길이에 따라 크기가 달라지므로 buf[100]만큼의 크기를 할당)
  • 실습1. 포인터를 이용한 문자열 입출력
    #include <stdio.h>
    #include <conio.h>
    
    void test04();					//포인터를 이용한 문자열 입출력 함수(5일차)
    
    
    int main()
    {
    	test04();
    }
    
    void test04() {
    	char* arr[10] = { "aaaaa", "bbbb", "cccc", "dd", "eeeee" };	//각각의 문자열은 메모리 상단에 상수 영역에 저장
    	for (int i = 0; i < 10; i++)
    	{
    		printf("arr[%d] : 0x%08x\n",i, arr[i]); //0x%08x에는 8자리의 16진수로 arr에 들어있는 값 표현
    	}
    }​​



  • 실습2. 키보드로 입력받은 내용을 buf[100]공간에 저장하고 arr배열의 6번째에 대입한 후, 이를 출력
    #include <stdio.h>
    #include <conio.h>
    
    void test04();					//포인터를 이용한 문자열 입출력 함수(5일차)
    
    
    int main()
    {
    	test04();
    }
    
    void test04() {
    	char* arr[10] = { "aaaaa", "bbbb", "cccc", "dd", "eeeee" };	//각각의 문자열은 메모리 상단에 상수 영역에 저장, arr의 0, 1, 2, 3, 4에 저장
    	char buf[100];
    	scanf("%s", buf);
    
    	arr[6] = buf; //입력받은 문자를 arr배열의 6에 저장
    
    	for (int i = 0; i < 10; i++)
    	{
    		printf("arr[%d] : 0x%08x\n",i, arr[i]); //0x%08x에는 8자리의 16진수로 arr에 들어있는 값 표현
    	}
    }​​​

    설정한대로 5번은 건너뛰고, 6번에[ 값이 입력되어 주소가 나타남
  • 실습3. 키보드로 입력받은 내용을 buf[100]공간에 저장하고 arr배열의 6번째, 7번째에 대입한 후, 이의 주소와 내용을 함께 출력
    #include <stdio.h>
    #include <conio.h>
    
    void test04();					//포인터를 이용한 문자열 입출력 함수(5일차)
    
    
    int main()
    {
    	test04();
    }
    
    void test04() {
    	char* arr[10] = { "aaaaa", "bbbb", "cccc", "dd", "eeeee" };	//각각의 문자열은 메모리 상단에 상수 영역에 저장, arr의 0, 1, 2, 3, 4에 저장
    	char buf[100];
    
    	printf("[6] ");
    	scanf("%s", buf);
    	arr[6] = buf; //입력받은 문자를 arr배열의 6에 저장
    
    	printf("[7] ");
    	scanf("%s", buf);
    	arr[7] = buf; //입력받은 문자를 arr배열의 6에 저장
    
    
    	for (int i = 0; i < 10; i++)
    	{
    		printf("arr[%d] : 0x%08x %s	\n",i, arr[i], arr[i]); //0x%08x에는 8자리의 16진수로 arr에 들어있는 값 표현
    		//뒤의 두 arr[i]는 모두 주소값을 나타냄. 변환자에 의해 0x%08x에서는 주소 출력, s에서는 해당 값인 문자열 출력
    	}
    }​​​​

    6과 7의 내용을 다르게 입력했으나, 동일한 내용으로 출력이 됨
    • 포인터가 동일한 메모리 공간을 가리키고 있어서 같은 내용이 들어가게 됨
  • 실습4. 위 문제를 해결하기 위해 7번에 입력하는 공간을  buf+50으로 변경 -> 7번 입력 시 6번 입력과 메모리 공간이 겹치지 않도록 분리하는 역할
    #include <stdio.h>
    #include <conio.h>
    
    void test04();					//포인터를 이용한 문자열 입출력 함수(5일차)
    
    
    int main()
    {
    	test04();
    }
    
    void test04() {
    	char* arr[10] = { "aaaaa", "bbbb", "cccc", "dd", "eeeee" };	//각각의 문자열은 메모리 상단에 상수 영역에 저장, arr의 0, 1, 2, 3, 4에 저장
    	char buf[100];
    
    	printf("[6] ");
    	scanf("%s", buf);
    	arr[6] = buf; //입력받은 문자를 arr배열의 6에 저장
    
    	printf("[7] ");
    	scanf("%s", buf+50);	//buf-> buf+50으로 변경
    	arr[7] = buf+50; //입력받은 문자를 arr배열의 7에 저장
    
    
    	for (int i = 0; i < 10; i++)
    	{
    		printf("arr[%d] : 0x%08x %s	\n",i, arr[i], arr[i]); //0x%08x에는 8자리의 16진수로 arr에 들어있는 값 표현
    		//뒤의 두 arr[i]는 모두 주소값을 나타냄. 변환자에 의해 0x%08x에서는 주소 출력, s에서는 해당 값인 문자열 출력
    	}
    }​​​​​

    입력되는 메모리가 잘 분리되어 각 배열 요소에 알맞은 주소와 내용이 들어감

포인터와 함수


  • 기본적인 인자 전달: 값을 복사하여 전달
    ex) Add(int a, int b); 함수가 있으면 두 개의 인자 필요
  • 호출 함수의 변수  -> 피호출된 함수의 입력값
  • Call-By-Value: 값을 인자로 전달하는 형태의 함수 호출
    • example) swap함수: a=10, b=20일 때, swap을 통해 두 개의 값을 교환하는 함수
      int main(void)
      {
      	int val1=10;
          int val2=20;
          swap(val1, val2);
          
          printf("val1: %d\n", val1);
          printf("val2: %d\n", val2);
          return 0;
      }
      
      void swap(int a, int b){
      	int temp=a;
          a=b;
          b=temp;
          
          printf("a: %d\n", a);
          printf("b: %d\n", b);
      }​
  • Call-By-Reference: 참조(를 가능케 하는 주소 값)를 인자로 전달하는 형태의 함수 호출
    int main(void)
    {
    	int val = 10;
        adder( &val );
        printf("val: %d", val);
        return0;
    }
    
    void adder(int* pVal)
    {
    	(*pVal)++;
    }​​
  • 포인터&const 키워드
    • const: 선언과 동시에 값 초기화만 가능(한 번 값을 설정하면 변경 불가)
      ->선언과 동시에 초기화를 하지 않거나, 이후 변경 시도 시 에러 발생

포인터의 포인터


  • 포인터의 포인터(=더블 포인터)
    • 싱글 포인터의 주소 값 저장

함수 포인터와 void 포인터


  • 함수 이름의 포인터 타입 결정: return type(자료형) + 매개 변수 type(자료형)
  • 함수 포인터 사용 시: 포인터가 fname이면, 함수 자료형 (*fname)(인자 자료형)으로 사용
    ex) 함수 이름이 fPtr1이고 return type이 정수이며, 매개 변수 type이 정수이면 int (*fPtr1) (int); 형식으로 사용
  • 패치 생성 시 주로 사용
  • void형 포인터: 자료형에 대한 정보가 없이 주소 정보를 포함하는 형태의 변수
    • 포인터 연산, 메모리 참조 등에 사용 불가능

실습 1:  함수 포인터를 이용하여 지정한 함수를 포인트하고, 이를 호출하여 함수 실행


1. 화면에 나타난 입력창에 사용할 함수의 번호를 입력
- test01함수: 숫자키에 대한 영단어(문자열) 출력
- test02함수: 문자열과 문자배열 출력
- test03함수: 포인터의 위치를 지정하고, 해당 위치에 문자열을 저장
- test04함수: 입력받은 문자열을 arr배열의 6번째, 7번째에 저장하고, 값과 주소값 출력

2. 함수 포인터를 이용하여 해당 함수를 불러오고, 실행

3. 함수 실행이 끝나면 다시 번호를 입력하여 함수 포인트. 종료하려면 0 입력

#include <stdio.h>
#include <conio.h>

void test01();					//숫자키에 대한 문자열 출력
void test02();					//문자열과 문자배열
void test03();					//포인터의 위치 지정
void test04();					//포인터를 이용한 문자열 입출력 함수(5일차)


//사용 함수 설정
void Dump(char* p, int len);	//메모리 공간 출력용 범용 함수
void Copy(char* p1, char* p2);


int main()
{
	int n;
	void* pf[] = { test01, test02, test03, test04 };//type이 정해지지 않은 포인터 배열, 내부의 배열요소는 함수의 주소
	void (*pfunc)();								//return값이 없고 인자도 필요 없는 포인터 함수 선언

	while (1) {
		printf("\n");
		printf("1. 숫자키에 대한 문자열 출력\n");
		printf("2. 문자열과 문자배열\n");
		printf("3. 포인터의 위치 지정\n");
		printf("4. 포인터를 이용한 문자열 입출력 함수\n");
		printf("0. 종료\n");
		printf("=====================================\n > ");
		scanf("%d", &n);
		printf("\n");

		if (n == 0)	return;	//0 입력 시 함수 종료

		pfunc = pf[n - 1];	//배열은 0부터 시작하므로 1을 빼줌
		pfunc();			//위에서 지정한 함수를 호출
	}

	//test01();
	//test02();
	//test03();
	//test04();

}



void test01(void) {

	char* str[] = { "Zero", "One", "Two", "Three", "Four",
		"Five", "Six", "Seven", "Eight", "Nine" }; // 문자열 포인터(*) 배열 선언

	printf("숫자키를 입력하면 해당 영단어를 표시합니다.(x는 종료)\n");
	while (1) {
		printf(" > 숫자: ");
		char c = getch();
		printf("%c\n", c);

		if (c == 'x' || c == 'X') break;//c | 0x20 == 'x'로 조건 넣어도 작동. c | 0x20을 통해 입력 값을 소문자로 변환

		int m = c - 0x30; //ASCII -> num값
		printf("%c: %s\n", c, str[m]); //입력 값c: str의 m번째 값.

		/*switch (c) {
		case '1':	printf("One\n");	break;
		case '2':	printf("Two\n");	break;
		case '3':	printf("Three\n");	break;
		case '4':	printf("Four\n");	break;
		case '5':	printf("Five\n");	break;
		case '6':	printf("Six\n");	break;
		case '7':	printf("Seven\n");	break;
		case '8':	printf("Eight\n");	break;
		case '9':	printf("Nine\n");	break;
		case '0':	printf("Zero\n");	break;
		default:	printf("숫자가 아닙니다.\n");	break;
		}*/
		printf("\n");
	}
}
void test02(void) {		//문자열과 문자배열
	char ca[] = "Hello";	//ca[0] = 'H', ..., ca[4] = 'o', ca[5] = null(\0)
	for (int i = 0; i < 6; i++) {
		printf("ca[%d]: %c (%02x) [%08x]\n", i, ca[i], ca[i], ca + i); //%02x: 2바이트씩 16진수로, [%08x]에는 주소 표현(ca + i)
	}

	int ia[] = { 10, 20, 30, 40, 50 };
	for (int i = 0; i < 6; i++) {
		printf("ia[%d]: %d (%08x) [%08x] \n", i, ia[i], ia[i], ia + i); //%08x: 8바이트씩 16진수로, [%08x]에는 주소 표현(ia + i)
	}

	int ia2[3][2] = { 10, 20, 30, 40, 50, 60 };
	for (int y = 0; y < 3; y++) {
		for (int x = 0; x < 2; x++) {
			printf("ia2[%d][%d]: %d(해당 위치의 데이터) [%08x](해당 위치의 주소) \n", y, x, ia2[y][x], ia2 + y); //마지막 ia2+y에서 ia2는 배열 명 + y해줄 때 y가 1 증가할 때 2개의 int가 포함. 따라서 8바이트씩 증가
		}
	}
}
void test03() {
	char buf[100];			//메모리 공간에 방 100개 만들기(안전한 메모리 공간 확보)
	char* pBuf;				//안전 메모리 공간중의 출력 위치 설정
	unsigned int addr;				//메모리 공간 중 출력 위치 지정을 위한 입력 변수(주소)
	char kBuf[100];			//출력할 문자열을 scanf로 입력받기 위한 공간을 미리 확보

	printf("buf(안전공간)의 주소는 %d[%08x]입니다.\n", (unsigned int)buf);	//%d에서는 10진수로 표시되므로 [  ]안에 참고용으로 16진수 출력
	printf("입력을 시작할 주소를 입력하세요: ");//buf이름의 메모리 공간 중 값이 할당할 시작 주소 입력(위의 안전공간 주소 참고)
	scanf("%d", &addr);							//기존 주소에 addr만큼 더해진 주소로 입력 값 저장

	pBuf = buf + addr;							//위에서 초기화한 addr의 값을 pBuf에 저장

	printf("문자열을 입력하세요: ");
	scanf("%s", kBuf);				//출력할 문자열 입력
	Copy(pBuf, kBuf);				//strcpy(복사할 위치, 복사할 내용)

	Dump(buf, 100);					//길이는 kBuf에서 설정한 100

	printf("\n");
}
void test04() {
	char* arr[10] = { "aaaaa", "bbbb", "cccc", "dd", "eeeee" };	//각각의 문자열은 메모리 상단에 상수 영역에 저장, arr의 0, 1, 2, 3, 4에 저장
	char buf[100];

	printf("[6] ");
	scanf("%s", buf);
	arr[6] = buf; //입력받은 문자를 arr배열의 6에 저장

	printf("[7] ");
	scanf("%s", buf + 50);	//buf-> buf+50으로 변경
	arr[7] = buf + 50; //입력받은 문자를 arr배열의 7에 저장


	for (int i = 0; i < 10; i++)
	{
		printf("arr[%d] : 0x%08x %s	\n", i, arr[i], arr[i]); //0x%08x에는 8자리의 16진수로 arr에 들어있는 값 표현
		//뒤의 두 arr[i]는 모두 주소값을 나타냄. 변환자에 의해 0x%08x에서는 주소 출력, s에서는 해당 값인 문자열 출력
	}
}



void Copy(char* p1, char* p2) {
	while (*p2) *p1++ = *p2++, * p1 = 0;;
	/*
	조건식:p2의 값(p2의 값이 null이 아니라면, 계속 수행)
	수행 내용: p1의 값에 p2값을 한글자씩 복사 => p2값의 마지막인 null값에 도달하면 p1값의 마지막에 null을 입력하며 완성
	*/
}
void Dump(char* p, int len) {							//p는 char 포인터(p는 주소값을 말함)
	for (int i = 0; i < len; i++) {						//함수 입력 시 입력받는 길이 len만큼만 반복
		if (i % 16 == 0)		printf("\n%08x", p);	//반복실행을 수행하기 위해 i가 16의 배수일 때 실행하도록 설정 -> 이 때 주소(p)를 출력
		if (i % 8 == 0)			printf("    ");			//8개를 출력할 때 공백 추가
		printf("%02x   ", (unsigned char)*p++);			//*의 의미: 포인터에서 p주소에 있는 값, 주소를 한칸씩 옮기며 출력
	}
}
정상 동작 및 종료 확인

구조체&사용자 정의 자료형


  • 구조체: 기본 자료형으로 새로운 사용자 정의 자료형을 만드는 문법 요소
  • 선언 방법: struct ~~{  }; 
  • 구조체 선언 예시1: point 이름의 구조체 선언
    struct point
    {
    	int x;
        int y;
    };​​
     
    • int x, int y: 구조체 멤버
  • 구조체 변수 선언 예시1: struct~}까지가 하나의 데이터 타입. 즉, p1, p2, p3는 모두 struct point{~} 데이터타입
    struct point
    {
    	int x;
        int y;
    } p1, p2, p3;
    
    int main(void)
    {
    	~~
    }
  • 구조체 변수 선언 예시2: 구조체를 별도로 선언 후 메인 함수 내에서 별도로 변수를 구조체에 맞게 선언 (일반적 방법)
    struct point
    {
    	int x;
        int y;
    }
    
    int main(void)
    {
    	struct point p1, p2, p3;
        ~~
        return 0;
    }​
    • 함수 선언 시 미리 프로토타입을 선언하고, 후에 사용하는 것과 비슷한 맥락
    • <stdio.h>와 같은 헤더파일에 위와 같은 방대한 양의 구조체가 정의되어 있음
  • 구조체 변수의 접근
    struct point
    {
    	int x;
        int y;
    }
    
    int main(void)
    {
    	struct point p1;
        p1.x=10;
        p1.y=20;
        ~~
        return 0;
    }​​
    • p1.x=10; => p1의 멤버 x에 10을 대입
  • 구조체 변수 초기화: 배열 초기화 문법과 일치
    struct person{
    	char name[20];
    	char phone[20];
        int age;
    };
    
    int main(void){
    	struct person p={"Free Lec", "02-3142+6702", 20);
        ~~
        return 0;
    }​
  • 구조체 배열의 선언
    struct person{
    	char name[20];	//이름을 기록하기 위해 20byte의 메모리 공간 확보
        char phone[20];	//전화번호를 기록하기 위해 20byte의 메모리 공간 확보
        int age;
    };
    
    int main(void){
    	struct person pArray[10];
        ~~
        return 0;
    }​​
    • 사람 한명에 이름, 전화번호, 나이를 저장하는 배열을 형성 -> pArray[0].name, pArray[0].phone, pArray[0].age
    • 이러한 정보를 20명의 데이터 생성
  • 구조체 배열 요소의 접근
    • pArray[1].age=10; => 두 번째 요소의 age에 접근
    • strcpy(pArray[1].name, "홍길동"); => 두 번째 요소의 name에 접근
    • strcpy(pArray[1].phone, "333-3333"); => 두 번째 요소의 phone에 접근
    • strcpy(string1, string2) 함수: string2를 string1에 지정한 위치로 복사하는 함수
      (string2에서 null이 위치한 지점까지 복사하여 string1에 대입)
      char name에는 문자 배열을 name = ~~형태로 입력 불가 -> strcpy 함수를 사용하여 입력

pArray[1]의 nam, phone, age에 접근하여 데이터 입력

 

  • 구조체 배열의 초기화
    • 선언과 동시에 초기화 가능
      struct person {
      	char name[20];
          char phone[20];
      };
      
      int main(void{
      	struct person pArray[3]={
          	{"Lee", "333"},
              {"Kim", "555"},
              {"SES", "777"}
          };
          .....
          return 0;
      }​
  • 구조체와 포인터
    • 구조체 포인터를 선언하여 구조체 변수를 가리키는 경우
    • 구조체의 멤버로 포인터 변수가 선언되는 경우
    • 구조체 & 배열 & 포인터 사용 예시
      struct person {
      	char name[20];
      	char phone[20];
      };
      int main()
      {
      	struct person man={"Thomas", "354-00xx"};
      	struct person * pMan;				//구조체 포인터 선언
      	pMan=&man;							//구조체 포인터에 man 변수의 주소 연결
      
      	// 구조체 변수를 이용한 출력.
      	printf("name : %s\n", man.name);	//구조체 멤버에 접근하기 위해 . 사용(man.name)
      	printf("phone : %s\n", man.phone);
      
      	// 구조체 포인터를 이용한 출력1.
      	printf("name : %s\n", (*pMan).name);	//(*pMan = man)
      	printf("phone : %s\n", (*pMan).phone);
      
      	// 구조체 포인터를 이용한 출력2.
      	printf("name : %s\n", pMan->name);		//화살표 기호를 통해 포인터에서 다이렉트로 멤버 변수에 접근 가능
      	printf("phone : %s\n", pMan->phone);
      
      	return 0;
      }​
    • 구조체 포인터를 이용한 출력2: pMan은 man 구조체 변수의 주소. printf 뒤의 pMan->name은 man.name, (*pMan.name)과 동일
    • pMan->name = man.name = (*pMan).name
    • pMan->name: 포인터에서 멤버 변수에 다이렉트로 접근
  • 구조체 변수와 주소 값 관계
    /* pointer_pointer.c */
    #include <stdio.h>
    
    struct simple {
    	int data1;
    	int data2;
    };
    int main()
    {
    	struct simple s={1, 2};
    
    	printf("address1 : %d\n", &s);
    	printf("address2 : %d\n", &(s.data1));
    	return 0;
    }​
  • 구조체 변수의 연산
    • 대입 연산(=)만 허용, 이외 사칙 연산은 적용 불가

실습 2:  구조체 변수의 반환 방식


  • 구조체 변수의 반환 방식: 위 실습 코드에 구조체 테스트 코드 추가
    1. 함수 선언 void test04(); 아래에 코드 추가
      void test05();					//구조체 테스트​
    2. 함수 선언 내용 void test04(); 아래에 코드 추가
      void test05(){
      	struct stTest {
      		int i;
      		float a;
      		char name[20];
      	} s1 = { 1, 3.14, "이름"};	
      		//구조체 변수 선언
      
      	struct stTest s2 = s1;
      	
      	printf("struct stTest s1: %d %f %s\n", s1.i, s1.a, s1.name);
      	printf("struct stTest s2: %d %f %s\n", s2.i, s2.a, s2.name);
      
      }​
    3. main 함수 내용 변경
      int main()
      {
      	int n;
      	void* pf[] = { test01, test02, test03, test04, test05 };//type이 정해지지 않은 포인터 배열, 내부의 배열요소는 함수의 주소
      	void (*pfunc)();								//return값이 없고 인자도 필요 없는 포인터 함수 선언
      
      	while (1) {
      		printf("\n");
      		printf("1. 숫자키에 대한 문자열 출력\n");
      		printf("2. 문자열과 문자배열\n");
      		printf("3. 포인터의 위치 지정\n");
      		printf("4. 포인터를 이용한 문자열 입출력 함수\n");
      		printf("5. 구조체 테스트\n");
      		printf("0. 종료\n");
      		printf("=====================================\n > ");
      		scanf("%d", &n);
      		printf("\n");
      
      		if (n == 0)	return;	//0 입력 시 함수 종료
      
      		pfunc = pf[n - 1];	//배열은 0부터 시작하므로 1을 빼줌
      		pfunc();			//위에서 지정한 함수를 호출
      	}
      
      	//test01();
      	//test02();
      	//test03();
      	//test04();
      
      }​
    4. 실행
      s2에 s1이 정상 대입되어 출력 확인

실습 3:  구조체 변수의 반환 방식


  • void test05()함수 내의 s1 변수를 이름을 선언하지 않고, 그 아래에 s1.name = "이름";을 입력하여 작동 확인
    void test05(){
    	struct stTest {
    		int i;
    		float a;
    		char *name;
    	} s1 = { 1, 3.14};	//이름은 선언하지 않음
    
    	s1.name = "이름";	//
    
    	struct stTest s2 = s1;
    	
    	printf("struct stTest s1: %d %f %s\n", s1.i, s1.a, s1.name);
    	printf("struct stTest s2: %d %f %s\n", s2.i, s2.a, s2.name);
    
    }​

    위와 동일하게 실행

실습2와 실습3의 차이점을 구조체의 사이즈(sizeof (~) 이용) 비교를 통해 확인


실습1:

char 메모리 크기를 20으로 설정하여 총 20(char [20])+4(int)+4(float)로 28byte

 
실습2:

stTest 구조체의 바이트가 16바이트로 표시(int 4byte, float 4byte, char *name 8byte) =&gt; char *name(주소값)은 8byte를 차지(x64bit에서)


[실습 2 vs 실습3 코드]

실습 2: name이 들어갈 변수의 메모리 크기를 20byte로 설정

	struct stTest {
		int i;
		float a;
		char name[20];
	} s1 = { 1, 3.14, "이름"};


실습 3: name이 들어갈 변수의 주소를 저장 -> 64비트에서 주소값은 메모리 크기 8byte를 차지 

	struct stTest {
		int i;
		float a;
		char *name;
	} s1 = { 1, 3.14};	

	s1.name = "이름";

 


  • 구조체 변수의 반환 방식: 기본 자료형 변수의 반환 방식과 동일
  • 중첩된 구조체
    • 구조체의 멤버로 구조체 변수가 올 수 있음
  • 중첩된 구조체 변수 초기화 방식
    : 배열을 초기화하는 방식과 유사(대입)
    • 다음의 코드에서 초기화 방법:
      struct point{
      	int x;
          int y;
      };
      
      struct circle{
      	struct point p;
          double radius;
      };
      
      int main(){
      	struct circle c={1, 2, 3.0};
      }​
    • case1: 위 방식대로 struct circle c={1, 2, 3.0}; 사용
    • case2: struct circle c={ {1, 2}, 3.0}; 사용 ( 대괄호 내의 {1, 2}는 point의 멤버 표현 )
    • case3: 초기화를 하지 않을 시 default값 설정 가능
      1. struct circle c={1, 2} -> x=1, y=2, radius = 0.0(default)
      2. struct circle c={ {1}, 2} -> x=1, y=0(default), radius = 2.0
  • typedef 키워드
    • typedef int INT; => 자료형 int에 새로운 이름 INT 부여
    • 적용방식1:
      struct Data
      {
      	int data 1;
          int data 2;
      };
      typedef struct Data Data;​
    • 적용방식 2:
      typedef struct Data
      {
      	int data 1;
          int data 2;
      } Data;​​​
      -> struct Data~ Data; 앞의 }까지가 구조체 정의
    • 위 코드를 적용하면 struct Data를 코드에서 Data로 사용해도 Data의 자료형으로 적용 가능
      struct Data val=~~; //이와 같이 길게 사용하던 것을 다음과 같이 짧게 사용 가능
      
      Data val=~~;​

      - 새로운 이름을 부여하더라도 기존의 방식대로 자료형 선언도 가능
        즉, Data val = ~~;와 struct Data val = ~~; 모두 사용 가능
  • 구조체 이름의 생략
    typedef struct
    {
    	int data 1;
        int data 2;
    } Data;​​​​
     
    • 이와 같은 방식으로 선언 시에는 변수 선언 시 자료형 이름으로 Data만 사용 가능(struct Data 사용 불가)
  • 공용체(Union): 하나의 메모리 공간을 둘 이상의 변수가 공유
    • 구조체 선언 시 struct s data a{~~}; 사용 => 각각의 변수가 개별 메모리 공간을 차지
      ex) int, char, double을 하나씩 선언 시 4+8+1 = 13byte 차지
    • 구조체 선언 시 struct u data b{~~}; 사용 => 각각의 변수가 같은 메모리 공간을 차지
      ex) int, char, double을 하나씩 선언 시, 가장 큰 double이 차지하는 8byte 내에 4byte의 int와 1byte의 char이 함께 존재


 
 
 
 

728x90