변수와 상수 고급이론 - C언어

홍성우·2023년 5월 16일

자료구조 (C언어)

목록 보기
9/15

변수의 값을 상수로 만들기 위한 방법은

1.리터럴 상수
2.심볼릭 상수

2가지 가 존재한다.
리터럴 상수란 'abc' 프로그래머가 직접 값을 하드코딩으로 값을 입력하는 것

심볼릭 상수란 const int num = 10 처럼 변수의 값을 상수화 시킨다.

심볼릭 상수를 하기 위한 방법

형한정어(const)
변수에 적용되는 문법으로서 컴파일러 최적화와 매우 밀접하게 관련된다.

변수를 상수화하는 역할을 한다.
즉 메모리를 읽기 전용 메모리로 만드는 기능을 담당한다.

const는 중요한 정보가 들어 있는 메모리를 보호하기 위한 것

const는 변수를 선언 및 정의 할때 상수화 한다. 이유는 유지보수를 쉽게 하기 위해서 이다.
그리고 컴파일러의 입장에서는 줄어든 변수 만큼 번역도 유리하며 성능이 향상된다.

  • const에 따라 성능이 좌우 된다.
#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>


int main() {

	int Input = 0;
	const int score = 70; // 심볼릭 상수(symbolic constant)
	printf("점수를 입력하세요");

	scanf_s("%d", &Input);
	// score = 60;
	if (Input >= score) puts("합격입니다.");
	else puts("불합격입니다.");


	return 0;
}

r-value상수 와 l-value 상수화

int main() {
	// l-value : 변수 , r-value : 값

	// 매개 변수가 상수형 포인터 이다. 따라서 함수에서 포인터가 가리키는 
	// 대상 메모리에 쓰기 시도 할수 없다.
	char szBuffer[32] = { "I am a boy" };

	int nData = 10;
	const int* pnData = &nData; // 포인터가 가리키는 대상을 상수화

	int* const pnNewData = &nData; // 포인터변수를 상수화

	// r-value
	// *pnData = 20; 
	// pnNewData = &nData+3;

	
	return 0;
}

volatile

형한정어 volatile을 적용하면 변수와 관련된 모든 연산에 대해 컴파일러가 최적화 규칙을 적용하지 않는다.
(const와는 정반대 역할 - const는 컴파일러 최적화)
*주로 엠베디드 프로그래밍에서 활용


#include <stdio.h>

int main(void)
{
	int nData = 10; 
	int i = 0;
	for (int i = 0; i < 10; ++i)
	{
		nData = 10;
	}

	printf("%d\n", nData);
		
		
	return 0;
}

  1. 최적화 하지 않았을때 - [Debug mode]
 // 어셈블리어 - debug mode
 	int nData = 10; 
005D1875  mov         dword ptr [nData],0Ah  
	int i = 0;
005D187C  mov         dword ptr [i],0  
	for (int i = 0; i < 10; ++i)
005D1883  mov         dword ptr [ebp-20h],0  
005D188A  jmp         __$EncStackInitStart+39h (05D1895h)  
005D188C  mov         eax,dword ptr [ebp-20h]  
005D188F  add         eax,1  
005D1892  mov         dword ptr [ebp-20h],eax  
005D1895  cmp         dword ptr [ebp-20h],0Ah  
005D1899  jge         __$EncStackInitStart+48h (05D18A4h)  
	{
		nData = 10;
005D189B  mov         dword ptr [nData],0Ah  
	}
005D18A2  jmp         __$EncStackInitStart+30h (05D188Ch)  

	printf("%d\n", nData);
005D18A4  mov         eax,dword ptr [nData]  
005D18A7  push        eax  
005D18A8  push        offset string "%d\n" (05D7B30h)  
005D18AD  call        _printf (05D10D2h)  
005D18B2  add         esp,8  
		
		
	return 0;
  1. 최적화 실행 상태 - [Release mode]
    반복문은 아예 실행조차 하지 않음
 // Release 모드 최적화
 
 int nData = 10; 
	int i = 0;
	for (int i = 0; i < 10; ++i)
	{
		nData = 10;
	}

	printf("%d\n", nData);
00ED1040  push        0Ah  
00ED1042  push        offset string "%d\n" (0ED2100h)  
00ED1047  call        printf (0ED1010h)  
00ED104C  add         esp,8  
		
		
	return 0;
00ED104F  xor         eax,eax  
}


  1. volitile을 적용하면 해당 변수에 대한 최적화를 모드 해제 한다.
    Release mode 에서도 최적화를 수행하지 않고 있다.
int main(void)
{
00F91040  push        ebp  
00F91041  mov         ebp,esp  
00F91043  push        ecx  
	volatile int nData = 10; 
00F91044  mov         dword ptr [ebp-4],0Ah  
	int i = 0;
	for (int i = 0; i < 10; ++i)
00F9104B  mov         eax,0Ah  
	{
		nData = 10;
00F91050  mov         dword ptr [nData],0Ah  
00F91057  sub         eax,1  
00F9105A  jne         main+10h (0F91050h)  
	}

	printf("%d\n", nData);
00F9105C  mov         eax,dword ptr [nData]  
00F9105F  push        eax  
00F91060  push        offset string "%d\n" (0F92100h)  
00F91065  call        printf (0F91010h)  
00F9106A  add         esp,8  
		
		
	return 0;
00F9106D  xor         eax,eax  
}
profile
제 블로그를 방문해 주셔서 감사합니다

0개의 댓글