FW 심화 과정/[2] STM32심화실습

0720 포인터,배열의 동작구조 / 함수포인터 / 구조체 / union ~176

천숭이 2022. 7. 22. 00:19

* 심볼 = 전역변수, 함수

* 포인터는 주소값을 가지므로 자료형에 상관없이 항상 4B크기로 고정

 

p.108, 110 실습

<포인터 변수에 대한 연산 및 데이터 참조>

#include <stdio.h>
#include "ARMCM3.h"
#include "core_cm3.h"
// #define SQUARE(x)	((x)*(x))

int fputc(int c, FILE *f)
{
	return ITM_SendChar(c);
}

int array[8];
char buf[10] = {0,1,2,3,4,5,6,7,8,9};
unsigned int * paddr;

int main(void) 
{
	//1.
	int *p = (int *) array;
	
	*p = -1;
	*(p+1) = 0x11111111;  // p+1 주소내의 값 변경 
	*p++ = 0x22222222;    // p주소 내의 값 변경하고 p+1처리 
	*p++ = 0x33333333;    // 위에서 +1된 p 주소 내 값 변경하고 p+1처리 (처음과 비교하면 p+2) 
	p[0] = 0x44444444;    // p+2 주소 
	p[-1] = 0x55555555;   // p-1 주소 
	*p = 0x66666666;      // p+2 현재 주소 값 변경 
	
    //2.
	paddr = (unsigned int *) &buf[0];
	
	printf("%#010x	\r\n",*paddr + 1);  // padder이 가리키는 값 + 1
	printf("%#010x \r\n", *(paddr + 1));  // padder의 다음 주소
	
	return -1;
	
}

결과 :

 

 

 


# 문자열, 배열 / ROM, RAM 관계

중간 수정이 안되는 포인터타입 char *p

//3.
char *p = "ABCDEF"; pointer -> X didn't work
//char p[] = "ABCDEF";  // array -> it works
printf("%#010x \r\n", (int)p);
printf("%s \n", p);

*p = 'X';   // = p[0] = 'X'
printf("%#010x \r\n", (int)p);
printf("%s \n", p);
/* 배열을 동적으로 할당하면 bin파일의 RO구역에 할당되므로, 나중에 수정해도 변경이 안된다.
   하지만 배열로 선언하면 bin파일의 RW(read and write)구역에 할당되므로, 나중에 수정이 가능하다  
*/

결과 :

- p의 주소가  0x6e8임을 확인. 메모리 값을찍어보니 "ABCDEF" 가 아스키코드값으로 잘 들어간것 확인.

- 포인터 p의 시작 주소값이 ROM에 저장되고, 그 시작 주소를 참조해 RAM에 접근해서 "ABCDEF" 출력하는 과정

- p의 첫 글자를 X로 변경하려 했으나 포인터는 bin의 RO파일에 할당되기에 중간에 수정이 불가능

 

 

중간 수정이 가능한 배열 타입 char p[]

- p는 변수이므로 RAM에 저장되고, "ABCDEF"는 문자열이므로 ROM의 bin의 RO구역에 할당.

- read write구역이므로 수정이 가능

- 값이 "XBCDEF"로 변경됨

 

 

 

 


# 값 참조

call by reference

 

call by value

 

 


# 함수포인터

void *fp()    -> 함수 선언
void (*fp) ();  -> 함수 포인터

 

- 사용하는이유 두가지

 

1. 함수를 매개변수로 전달하는 경우

함수포인터_끝에 괄호           ! =             포인터_(*)필요

함수타입과 매개변수를 조합해서 구별

 

 

 

2. 부팅시 bootloader에서 application으로 넘어갈 경우

 

int pFunc(int a, int b)
{
   printf("%s \r\n", __func__);  // print function name
   return (a + b);
}
int addr;
int (*fp)(int, int);

int main()
{
   *(int *)0x20000010 = (int)pFunc; // 0x20000010 번지에 pFunc 주소를 입력 
   
   int addr = *(int *)0x20000010;  // addr에 함수포인터변수의 주소를 저장 
   
   fp = (int (*)(int, int))addr;  // fp에 addr타입을 구체적으로 명시하고 대입
   
   int a = fp(1, 2);
   printf("%d \r\n", a);
}

 

- pFunc가 할당된 주소는 0x000003d1
츨력 확인 / pFunc 메모리값 확인

 

 

 


# 구조체 Struct

선언 : 구조체만 선언 , typedef으로 선언(컴파일러에게 알려줌)

정의 : 구조체 변수 정의(메모리에 할당)

 

# 구조체 packing 방법

#pragma pack(1)  // 1Byte 단위로 패킹함으로써 남는 메모리 없이
#pragma pack()   // 패킹 해제