프로그래밍 공부

전체 글 700

  • 매개 변수 개수가 고정되지 않고 호출할 때 마다 인자의 개수가 달라질 수 있는 경우를 말한다. 가변인자를 사용하려면 C언어에서는 stdarg.h 라이브러리를 C++에서는 cstdarg 라이브러리 를 사용한다. 이 라이브러리 를 사용하면 va_list, va-start, va_arg, va_copy, va_end 등의 매크로 함수를 이용하여 가변인자 를 처리할 수 있다. 대표적인 예시는 printf() 함수가 있는데, printf() 함수는 매개변수의 개수가 고정되어있지않으며, 호출할 때 마다 인자의 개수와 형식이 달라질 수 있다는걸 알 것이다. 따라서 printf()함수는 가변인자를 사용하여 처리하게된다. 다음과 같은 함수를 예시로 살펴보자. 위 함수를 살펴보면, print_number 함수를 선언하고,..

  • 스택 프레임은 함수가 호출될 때 마다 새로운 메모리 블록이 할당되어 사용되며, 함수가 실행을 완료하고 반환하면, 해당 스택 프레임은 제거된다. 이러한 스택 프레임의 생성과 제거는 호출스택(Call Stack) 구조에 의해 관리된다. 스택 프레임에는 함수에서 선언된 지역변수, 매개변수, 복귀주소, 호출 스택 포인터(Caller Stack Pointer) 등이 저장된다. 함수에서 변수를 사용하거나, 매개변수를 전달할 때마다 스택포인터 가 이동하면서 해당 변수가 저장될 위치를 지정한다. 함수 실행이 완료되면, 스택 포인터가 원래 위치로 되돌아가며, 이전에 호출된 함수의 스택프레임이 반환될 준비를 한다. 즉, 스택 프레임(Stack Frame)은, 함수에서 선언된 지역변수, 매개변수, 복귀주소, 호출 스택 포인..

  • 호출 스택 포인터 는 C/C++에서 함수 호출이 발생할 때 스택 메모리 구조를 관리하는데 사용되는 포인터 이다. 스택 메모리는 후입선출(Last-In-First-Out) 방식으로 동작한다. 함수가 호출될 때 마다 호출 스택 프레임(Call Stack Frame)이 스택에 쌓이고, 반환될 때마다 해당 프레임이 스텍에서 제거된다. 이때 스택 포인터(Call Stack Pointer)는 현재 스텍프레임의 맨 위를 가리키는 포인터 이다. 이는 스텍메모리 에 대한 접근을 제어하고, 호출 스택 프레임의 크기를 결정하는데 사용된다. ( 스택 프레임에 가장 최근에 들어온 프레임의 바로 윗부분. 다음 프레임이 들어올 시작지점을 가리킨다.) C++에서 n부터 1까지의 정수를 출력하는 재귀함수를 통해서 스택포인터를 살펴보자..

  • C++에서는 구조체를 선언하고 내부에 함수를 생성해줄 수 있다. 그러나, 구조체는 선언전에 메모리할당이 발생하지 않는다. 그럼으로 함수는 CODE 영역에 메모리가 할당되어 실행되게 되는데. 구조체 안에 함수가 존재하지 않음으로 사실 구조체는 함수를 실행할 수 없다. 구조체 내부에서 함수를 선언하고 실행하는건 다음과 같은 방식을 따른다. Print함수가 구조체 내부에서 선언됨을 볼 수 있다. 그러나, 함수는 구조체 내부에 존재하여도 구조체는 선언 전에 메모리 할당이 일어나지 않음으로 함수 메모리에 존재하나. 실행할 수 없다. 그럼으로 구조체 내부에 존재하는 함수는 __thiscall 을 내부에 붙여서 구조체 내부에서 함수를 다시 호출해준 뒤. 괄호 안에 자신의 구조채를 선언하여 동작하게 된다. 즉, 위에서..

  • 심볼 테이블 은 컴파일러가 소스코드를 분석하는 과정에서 생성된다. 이는 변수, 함수 등의 식별자와 해당 식별자가 가리키는 메모리 위치 등의 정보를 저장하는 데이터 구조이다. 다음 코드와 함께 예시를 살펴보자. 위 코드에서 변수 x는 식별자(identifier) 로서 main함수 내부에서 선언되었다. 이때, 컴파일러는 x라는 식별자와 해당 변수가 선언된 메모리 위치 등의 정보를 심볼 테이블에 저장하게 된다. 즉, 심볼 테이블은 소스코드 를 분석하는 과정에서 생성되며, 변수, 함수 등의 식별자와 해당 식별자가 가리키는 메모리 위치 등의 정보를 저장하게 된다. 이 정보를 바탕으로 컴파일러가 실행파일을 생성하게 된다. 만약, 위 코드가 실행되었을 경우 심볼 테이블은 다음과 같이 생성될것이다. 식별자 이름 선언 ..

  • 프로그래밍 언어는 선언시 형식, 변수, 초기화 의 순으로 이루어진다. 다음 예시를 살펴보자. 여기서 int a = 10; 이라는 변수가 선언되었을 때. L-value 는 a이고, R-value 는 10 을 의미한다. L-value R-value 변수 선언시 왼쪽의 변수명 또는, 대입연산자가 들어갔을 시의 왼쪽 변수를 이야기한다. 변수 선언시 오른쪽의 상수 또는 대입연산자가 들어갔을 시의 오른쪽 상수, 변수 를 이야기한다. 식이 끝나도 나중에 다시 접근이 가능하다. int a를 선언했을 때, 나중에 a를 선언함으로써 다시 호출이 된다. 식이 끝나면 나중에 다시 접근할 수 없다. int a = 10 이라고 했을 때. 10이라는 상수가 선언된 후 식이 끝나면 10에 접근할 방법이 사라진다. 변수 그자체이기 때..

작성일
2023. 4. 20. 01:14
작성자
WDmil
728x90

매개 변수 개수가 고정되지 않고 호출할 때 마다 인자의 개수가 달라질 수 있는 경우를 말한다.

 

가변인자를 사용하려면 C언어에서는 stdarg.h 라이브러리를 C++에서는 cstdarg 라이브러리 를 사용한다.

 

이 라이브러리 를 사용하면 va_list, va-start, va_arg, va_copy, va_end 등의 매크로 함수를 이용하여 가변인자 를 처리할 수 있다.

 

대표적인 예시는 printf() 함수가 있는데, printf() 함수는 매개변수의 개수가 고정되어있지않으며, 호출할 때 마다 인자의 개수와 형식이 달라질 수 있다는걸 알 것이다. 따라서 printf()함수는 가변인자를 사용하여 처리하게된다.

 

다음과 같은 함수를 예시로 살펴보자.

위 함수를 살펴보면, print_number 함수를 선언하고, int num, ... 으로 매개변수 를 받아오는 걸 볼 수 있다.

그 후, va_list args 를 선언하고, va_start(args, num) 을 통해 시작값과 끝 값을 사용하여, 입력된 모든 값을 출력하는 걸 확인할 수 있을것이다.

 

즉, 가변인자 는 함수가 가질 수 있는 최대개수의 변수를 따로 지정하지 않아도 배열값을 활용하여 형변환을 통해 받아올 수 있다는걸 알 수 있다.

728x90
작성일
2023. 4. 20. 00:57
작성자
WDmil
728x90

스택 프레임은 함수가 호출될 때 마다 새로운 메모리 블록이 할당되어 사용되며, 함수가 실행을 완료하고 반환하면,

해당 스택 프레임은 제거된다.

 

이러한 스택 프레임의 생성과 제거는 호출스택(Call Stack) 구조에 의해 관리된다.

 

스택 프레임에는 함수에서 선언된 지역변수, 매개변수, 복귀주소, 호출 스택 포인터(Caller Stack Pointer)

등이 저장된다.

 

함수에서 변수를 사용하거나, 매개변수를 전달할 때마다 스택포인터 가 이동하면서 해당 변수가 저장될 위치를 지정한다.

함수 실행이 완료되면, 스택 포인터가 원래 위치로 되돌아가며, 이전에 호출된 함수의 스택프레임이 반환될 준비를 한다.

 

즉, 스택 프레임(Stack Frame)은, 함수에서 선언된 지역변수, 매개변수, 복귀주소, 호출 스택 포인터가 저장되는 후입선출의 저장공간이다.

728x90
작성일
2023. 4. 20. 00:38
작성자
WDmil
728x90

호출 스택 포인터 는 C/C++에서 함수 호출이 발생할 때 스택 메모리 구조를 관리하는데 사용되는 포인터 이다.

 

스택 메모리는 후입선출(Last-In-First-Out) 방식으로 동작한다. 함수가 호출될 때 마다

호출 스택 프레임(Call Stack Frame)이  스택에 쌓이고, 반환될 때마다 해당 프레임이 스텍에서 제거된다.

 

이때 스택 포인터(Call Stack Pointer)는 현재 스텍프레임의 맨 위를 가리키는 포인터 이다. 이는 스텍메모리 에 대한 접근을 제어하고, 호출 스택 프레임의 크기를 결정하는데 사용된다.

( 스택 프레임에 가장 최근에 들어온 프레임의 바로 윗부분. 다음 프레임이 들어올 시작지점을 가리킨다.)

 

C++에서 n부터 1까지의 정수를 출력하는 재귀함수를 통해서 스택포인터를 살펴보자.

실행 시 5에서 1까지 출력된다.

위 코드에서 호출 스택 포인터는 countdown함수의 호출과 반환과정에서 사용되는데,

 

countdown 함수가 호출될 때 마다 호출 스택 프레임이 생성되고, 호출스택 포인터는 그 프레임의 맨 위를 가리키게 된다.

countdown 함수가 반환될 때 마다 해당 프레임이 스택에서 제거되고, 호출 스택 포인터는 바로 이전 스택 프레임의 맨 위를 가리키게 된다.

여기서 반환 시 어떤식으로 일어나게 되냐면,

즉, 위 코드에서 countdown 함수가 반환될 때 마다 반환된 프레임이 스택에서 제거되고, 호출 스택 포인터는 바로 이전 스텍 프레임의 맨 위를 가리키게 된다.

위 코드에서는 재귀함수 임으로, countdown이 실행되었을 때마다 5부터 실행되서 1까지, 5,4,3,2,1 의 순서대로 스텍프레임이 쌓이게 되고, 1이 if문에 충족하지 않음으로, 출력값을 내보낸이후 스택 프레임에서 반환되어, 1,2,3,4,5 순서대로 반환되게 된다.

 

정리하자면

호출 스택 포인터(Stack Pointer)호출 스택 프레임(Call Stack Frame) 의 가장 최근에 들어온 프레임의 바로 위를 가리키게 되고, 이는 반환시키는 프레임의 바로 다음 위치값을 나타낸다.

 

여담으로, java에서는 호출 스택 포인터 가 아닌 스택 프레임 포인터(Stack Frame Pointer) 라고 말하고 C/C++ 과 다르게 자동메모리 관리를 지원한다.

 

어셈블리어에서는 비슷한 ESP(Register Stack Pointer)라는 레지스터가 스택포인터 역할을 한다.

728x90

'컴퓨터 용어 정리' 카테고리의 다른 글

가변인자(variable argument)  (0) 2023.04.20
스택 프레임(Stack Frame)  (0) 2023.04.20
심볼 테이블 ( Symbol Table )  (0) 2023.04.19
L-value, R-value  (0) 2023.04.19
댕글링 포인터(Dangling Pointer)  (0) 2023.04.19
작성일
2023. 4. 19. 19:50
작성자
WDmil
728x90

C++에서는 구조체를 선언하고 내부에 함수를 생성해줄 수 있다.

그러나, 구조체는 선언전에 메모리할당이 발생하지 않는다. 그럼으로 함수는 CODE 영역에 메모리가 할당되어 실행되게 되는데. 구조체 안에 함수가 존재하지 않음으로 사실 구조체는 함수를 실행할 수 없다.

 

구조체 내부에서 함수를 선언하고 실행하는건 다음과 같은 방식을 따른다.

구조체 안에서 선언된 Print함수를 살펴보자.

Print함수가 구조체 내부에서 선언됨을 볼 수 있다. 그러나, 함수는 구조체 내부에 존재하여도 구조체는 선언 전에 메모리 할당이 일어나지 않음으로 함수 메모리에 존재하나. 실행할 수 없다.

 

그럼으로 구조체 내부에 존재하는 함수는 __thiscall 을 내부에 붙여서 구조체 내부에서 함수를 다시 호출해준 뒤.

괄호 안에 자신의 구조채를 선언하여 동작하게 된다.

 

즉, 위에서 보는것은 구조체가 함수를 실행한것 처럼 보이나. 사실 함수는 이미 존재하고, 구조체에서 함수를 실행하는 순간

 

함수는 자기자신을 재선언하게되고. 구조체를 매개변수로 받아와서 동작하게 되는것이다.

 

이는 구조체가 생성되고 선언되기 전에는 메모리에 잡히지 않기 때문에 발생하는 일이다.

 


C++에서는 L-value 와 R-value를 활용한 포인터 연산과 비슷하게 동작하는 레퍼런스 연산을 지원한다.

우선 L-value와 R-value가 무엇인지 부터 살펴보자.

https://inradestrt.tistory.com/166

 

L-value와 R-value는 각각 식이 끝나도, 나중에 접근이 가능한값, 식이 끝나면 나중에 다시 접근이 불가능한 값. 을 이야기한다.

 

이때, C++에서 사용할 수 있는 래퍼런스 연산을 사용할 수 있다. 예시는 다음과 같다.

각각 189줄과 23번줄은 함수이다.

함수에서 int를 가져올 때 & 연산자와 &&연산자를 넣게 되는데, 형식지정자 옆에 붙는 &연산자는

 

L-value 레퍼런스

 

라고 부른다. 변수의 별명이라는 이야기인데, 간단한 코드 동작사항으로 어떻게 동작되는지 살펴보자.

다음 예시에서 볼 수 있듯, r과 val은 같은 데이터값을 가리키는 이름이 된다. 주소와는 약간 비슷하면서도 다른데,

 

레퍼런스는 주소값같이 접근가능한 저장공간을 가지지 않는다. 조금이상한 이야기 같기는 해도, 그림으로 설명하면 다음과 같다.

위 이미지대로 val과 r은 데이터를 지칭하는 이름이 되고, *ptr은 데이터를 가리키는 주소값이 된다. 이렇게 되어있는 이유는,

val과 r은 데이터 그자체를 가리키는 이름이 되고, 이를 이용한 다른 연산 활용방안이 아예 존재하지 않기 때문에 저장공간이 할당이 될 때 심볼 테이블에 저장되게 된다.

int && rr = 10; 와 같이 활용할 수 도 있는데, 이는 const int rr 과 같은 역활을 한다. & 와 &&가 있다고, 별칭의 별칭. 이런식으로 해석되는것 이 아닌, &&이 들어감 으로써 상수와 같은 효과를 낸다.

 

프로그래머 들의 프로그램 의도를 나타낼 때 사용할 수 있다. 즉, 받아오는 데이터가 변경되지 않음. 을 펑션에 나타낼때 사용한다.

 

코드의 직관성을 높이는데 사용할 수 있다.

 

사실 void print(int a) 와 void print(int&& a)는 동작사항 시 차이가 없다.

그러나, int a가 선언되는 것 보다 &&가 붙어있음으로 해당 변수는 받아와서 복사한 후 처리한다.

라는 프로그래머의 의도를 쉽게 이해할 수 있음으로 직관성을 높여준다.


C++에서는 범위기반의 for문 순환연산을 허용한다. 예시를 살펴보자.

이때 피보나치 수의 배열을 다음과 같이 선언하면, for문 순환은 9번째 줄과 같다.

이는, 기본적인 배열순환방법이며 int i를 통해 임의의 배열위치에 접근이 가능한 장점이 있다.

 

그러나, int i 를 통한 임의의 위치에 접근이 가능하나, 아날로그 파형같이 연속된 데이터에 접근하기 위한 연산방법으로는

적합하지 않는 방법이 될 수 있다.

만약, 다음과 같은 위치에 접근하고자 한다면, 디지털 신호에서는 1 이상의 값이 표기된 값에 순차접근을 하면 가능하나, 아날로그 위치에서는 접근이 난해할것이다. 저 위치에 어떻게 접근할 것 인가?

 

이를 위해 C++에서는 다음과 같은 방법을 사용할 수 있다.

 

이것과 같은 순환방식을 사용하는 것 을 볼 수 있다.

 

이는, finbonacci 배열에 접근하여 순차연산을 진행하는데, int i 같은 데이터 가 아닌 처음부터 끝까지 자동으로 배열순환연산을 진행해준다.

 

한번 접근 할 때마다 원하는 연산을 진행할 수 있다.

 

그러나, int i 같이 원하는 배열 위치에 접근하기에는 애로사항이 있을 수 있는 단점이 있다.

 

또한 new와 malloc같은 동적배열생성 시 배열의 최대값을 알 수 없기 때문에 사용할 수 없다.

이렇게 접근하는 방법은 사용할 수 없다.

728x90
작성일
2023. 4. 19. 19:39
작성자
WDmil
728x90

심볼 테이블 은 컴파일러가 소스코드를 분석하는 과정에서 생성된다.

이는 변수, 함수 등의 식별자와 해당 식별자가 가리키는 메모리 위치 등의 정보를 저장하는 데이터 구조이다.

 

다음 코드와 함께 예시를 살펴보자.

위 코드에서 변수 x는 식별자(identifier) 로서 main함수 내부에서 선언되었다.

 

이때, 컴파일러는 x라는 식별자와 해당 변수가 선언된 메모리 위치 등의 정보를 심볼 테이블에 저장하게 된다.

 

즉, 심볼 테이블은 소스코드 를 분석하는 과정에서 생성되며, 변수, 함수 등의 식별자와 해당 식별자가 가리키는 메모리 위치 등의 정보를 저장하게 된다.

 

이 정보를 바탕으로 컴파일러가 실행파일을 생성하게 된다.

 

만약, 위 코드가 실행되었을 경우 심볼 테이블은 다음과 같이 생성될것이다.

식별자 이름 선언 위치 참조 위치 데이터 타입
main CODE영역 CODE 영역 함수 타입
x 스택 영역 스택 영역 int 타입
std::cout CODE영역 스택 영역 객체 타입

728x90

'컴퓨터 용어 정리' 카테고리의 다른 글

가변인자(variable argument)  (0) 2023.04.20
스택 프레임(Stack Frame)  (0) 2023.04.20
호출 스택 포인터(Call Stack Pointer)  (0) 2023.04.20
L-value, R-value  (0) 2023.04.19
댕글링 포인터(Dangling Pointer)  (0) 2023.04.19
작성일
2023. 4. 19. 18:56
작성자
WDmil
728x90

프로그래밍 언어는 선언시 형식, 변수, 초기화 의 순으로 이루어진다. 다음 예시를 살펴보자.

여기서

 

int a = 10;

이라는 변수가 선언되었을 때.

L-value 는 a이고,

R-value 는 10 을 의미한다.

 

L-value R-value
변수 선언시 왼쪽의 변수명 또는, 대입연산자가 들어갔을 시의 왼쪽 변수를 이야기한다. 변수 선언시 오른쪽의 상수 또는 대입연산자가 들어갔을 시의 오른쪽 상수, 변수 를 이야기한다.
식이 끝나도 나중에 다시 접근이 가능하다.
int a를 선언했을 때, 나중에 a를 선언함으로써 다시 호출이 된다.
식이 끝나면 나중에 다시 접근할 수 없다.
int a = 10 이라고 했을 때. 10이라는 상수가 선언된 후 식이 끝나면 10에 접근할 방법이 사라진다.
변수 그자체이기 때문에 항상 원본 또는 원본의 값을 이야기한다. 대입연산자가 이루어진 후에 들어가는 상수, 변수는 그 원본이 아니라 복사된 복사체가 L-value에 삽입됨으로 원본이 아니라 할 수 있다.

 

L-value와 R-value의 특징은 위와 같다.

728x90