• 포인터

주소 저장 목적의 변수

 

&[주소연산자] - 해당 변수의 주소값을 반환


*[간접 참조 연산자] - 포인터 앞에 붙을시에 포인터가 가진 주소에 데이터를 반환

 

int * a 가 있다면 a는 int형 포인터다

 

이 말은 int가 이 주소의 데이터형 단위 라는 것이며

 

이 데이터형 단위로 읽는다는 것이다

 

 

 


 

  • NULL , nullptr

NULL 은 상수 0 이라고 define되어 있다

그렇기에 포인터외의 자료형도 사용할수가 있다

 

 

nullptr C++에서 생겼으며 말 그대로 NULL값을 가진 포인터를 의미하여 포인터끼리만 연산이 가능하다

 

모두 포인터에 사용했을시에 핵심은 데이터가 0인지 판단하는것이지 정상적으로 할당받은 데이터를 판단할수는 없다

                                                                                          [ex) new로 할당 받은 주소]

 


 

  •  New

new 자료형 - 운영체제에서 자료형만큼의 데이터공간의 주소를 반환

저렇게 new만 써도 메모리가 할당된다

그렇기에 저 반환하는 주소를 포인터에 대입시키는 것이다

 

저 new의 실체는 operator new 라는 함수이다

 

배열형식으로 선언은

new 자료형 [num]

 


 

  • Delete

new가 메모리를 운영체제에서 받아왔다면 이건 운영체제에 받아온 메모리를 반환한다

 

이것도 마찬가지로 operator delete 가 본체이다

 

array형식을 delete할때는 " delelte [ ] 식별자  " 로 해줘야한다

그 이유는 소멸자 문제가 발생하기 때문이다.

[ 위에는 소멸자가 딱히 관련이 없기에 delete[ ] 를 delete로 바꾸어도 정상으로 돌아가긴한다 ]

소멸자가 한번 호출후 에러가 난다

 

 

이러한 주소하나만 delete에 넘겨주어도 주소가 가지고있는 할당된 메모리가 해제되는 이유같은 내용은

다른 글에 다시 정리한다

[ 작성중인 글 ]

https://ddidding.tistory.com/23

 


 

  • 배열 포인터

[ ] 를 사용하여 해당 인덱스의 배열 값을 나타내듯이 사용할 수 있다

 

+ 와 - 를 이용하여 해당 인덱스의 주소를 알아낼 수 있다

여기서의 0, 1, 2, 3 이 의미하는것은 정수 0, 1 이 아니라 a 포인터가 담는 자료형(int) 의 크기만큼 주소를 더한다는 뜻

 

그렇기에 int형의 크기 4 BYTE 만큼 주소가 증가한걸 볼 수 있다

 

위에 연산이 주소를 나타내는 것이기에

주소의 값을 나타내는 간접 참조 연산자 ( * ) 를 같이 사용하면 그 주소가 가지고있는 값을 확인할 수 있다

 

여기서 해당값의 주소를 알려주는 주소연산자( & )를 사용하면

다시 주소가 나오겠지ㅋㅋㅋ

 

배열과 포인터의 차이점이라면

 

1. 포인터는 변수이고

배열의 식별자는 상수라는 점이다

 

2. Sizeof를 사용했을 때

a 와 b 모두 첫번째 값의 주소를 나타내지만

 

포인터는 주소의 크기 ( 자료형의 크기가 아님 )

배열은 배열의 크기가 출력된다

 

 

문득 VS로 메모리 디버깅을 하는중에 의문이 들었다

 

이게 내 컴퓨터 메모리의 처음부터 끝까지의 데이터를 보여주는건가? 그게 맞다면

 

지금 다른프로그램도 실행중인데.. 다른 프로그램의 데이터도 메모리디버깅창에서 확인이 되는건가?

 

궁금해서 찾아봤다

 

 


Logical Memory - 프로그램마다 각자 가지는 메모리 , 모두 0부터 시작한다

 

주소가 0 ~ 100 까지인 컴퓨터에 메모장과 그림판 프로그램 두개가 실행되고 있다고 치면

 

메모장 Logical Memory에 주소 0 ~ 100이 있고

 

그림판 Logical Memory에 주소 0 ~ 100이 있는것이다

 

그래서 메모장의 0번 데이터와 그림판의 0번데이터가 다를수 있는것이다

 

그래서 VS의 메모리 디버깅의 주소값도 VS만의 Logical Memory주소를 참조하는 것이였다!

 


physical memory - 프로그램이 실제 메모리에서 올라가는 공간

 

0부터 쭉 모든 프로그램의 데이터가 올라간다고 한다


 

더 깊은 내용이 있지만 내게 필요한 정보는 일단 여기까지~~

'공통' 카테고리의 다른 글

부동 소수점의 오차  (0) 2022.01.25
  • 구조체

배열에 여러 데이터형을 넣고 싶다 -> 구조체

 

각 항목을 멤버

 

구조체 태그를 식별자로 사용가능

 

태그를 생략할 수 있는데 태그가 없으니 변수를 생성할 수 없다, 그렇기에 변수 정의와 함께 사용

앞으로 MyStruct밖에 사용 불가

 

멤버들이 저장되는 메모리크기는 가장 큰 자료형의 크기로 저장됨

 

이러한게 많이 비효율적이라 생각이 들면 비트필드 이용

 

지정한 비트만큼만 데이터가 저장된다 ( 컴파일러에 따라 다르지만 VsC++에서는 정수형 & bool형 으로만 사용가능 )

단 자료형보다 큰 비트제어는 불가능하다

 

Signed 일경우 맨 앞자리는 부호비트로보고 나머지를 계산

ex)

1) b에 13를 넣는다

2) 13 = 1101 (이진수)

3) b는 3비트만 사용하여 "101"로 데이터가 잘림

4) 맨앞은 부호비트로 채용, 음수가 됨

5) 나머지 데이터 "01"이 음수이므로 음수형으로 2의 보수를 취한다 [ 십진수를 음수 이진수로 표현 2의 보수 취하기]

6) 그럼 "10" 이 되므로  3이다

6) 최종적으로 -3 데이터 가 들어가있는게 된다 

 

unsigned는 부호비트가 없으므로 어디서 잘리는지만 보면 된다

ex)

1) c에 5를 넣는다

2) c = 101 (이진수)

3) c는 2비트만 사용하여 "01" 로 잘림

4) 최종적으로 1저장

 

※ 구조체와 클래스 차이 공부 필요

 


  • 공용체 (Union)

가장 큰 변수의 메모리를 모든 변수가 공유함

 

 

공용체 , 익명공용체

 

유니온의 크기는 가장 큰값이여도 각자 사이즈는 다르다
같은 주소

이런식으로 const도 바꿀수있나보다

 


  • 열거형

상수형에 이름붙인 나열된 자료형

 

경험상 어떠한 카테고리안의 항목을 다룰 때 편한거 같다

 

예를들어 플레이어의 상태 카테고리라면

이런식으로 쓸수있다

태그명(위에서 State)는 변수를 만들지 않을거면 사용하지 않아도 된다 , 상수값 중복가능

 

데이터형이 Enum형일수도있고 int형으로 될수도있다 그렇기에 산술연산이 가능한데

 

산술연산 가능은 컴파일러마다 다르다 (하지만 이식성을 위해 쓰지말자), 대입연산과 비교연산 가능

 

따로 초기화 해주지 않는 이상 계속 0부터 1씩 증가되어 값이 대입된다

[ 중간에 딱 한값만 100으로 넣어도 그뒤에는 101, 102 .... 이런식이다 ]

 

변수에 값 대입시에 무조건 해당 Enum에 정의된 열거자(식별자)를 넣어줘야하는데 

ex) playerState = Idle;

 

명시적인 데이터형 변환을 사용하면 가능하다

ex) playerState = State(99) // "99"라는 int형을 State형으로 강제 형변환

 

저렇게 99라는 없는 상수도 넣을수 있는데 최대값 범위가 공식으로 있다고 하는데 사실 잘 모르겠다 해봤는데 

그 공식에서 나온 값을 넘어서도 출력이 잘 된다

 

추가+

enum은 몇가지 정수형에 의해 표현되는데

C++98 이하 버전에서는 실행하는 방식에 따라 달랐지만 C++11이후로 선택할수있는 문법이 생겼다

언리얼은 기본적으로 GC 기능을 제공하는데

 

C++ 변수를 에디터(블루프린트)에서 어떤 속성을가진 변수로 나타낼지 정의하는 매크로

 


  • Edit, Visible

두개를 같이 사용할 수 없으며 사용할 경우 둘중 하나만 사용가능하다

 

Edit은 말 그대로 편집이 가능한가이다, 편집을 하려면 보여야하니까 Visible과 같이 사용하는게 의미가 없는거 같다

 

Visible은 편집을 할수없고 "보일것인가" 에 대한 지정자다

 

 

이 두가지 각 DefaultsOnly, InstanceOnly, Anywhere 세가지 종류가 있다

 

DefaultsOnly = 에디터 창 안에서 유효

InstanceOnly = 월드에 배치된 Actor의 디테일창에서 유효

Anywhere = 모두 유효

 


  • BlueprintReadOnly, BlueprintReadWrite

BlueprintReadOnly = 블루프린트 노드에서 Get만 이용할 수 있다

BlueprintReadWrite = 블루프린트 노드에서 Get,Set 이용할 수 있다 [ ※ public 멤버 변수에 대해서만 가능 ]

 


  •  BlueprintGetter , BlueprintSettet

BlueprintGetter = 해당 변수의 Get이 호출 될때 같이 실행될 커스텀 함수연결

BlueprintSetter = 해당 변수의 Set이 호출 될때 같이 실행될 커스텀 함수연결

 

UPROPERTY 와 UFUNCTION 둘다 써줘야 한다

변수쪽은 함수의 이름을, 함수쪽은 그냥 키워드만

밑의 결과를 보면 Set에서 뽑아내서 PrintString에 연결하는 것이 Get을 실행시켜서 얻어오는듯하다

 


  • MetaData

변수의 속성을 다룬다

ex) float의 최대 최소값,  vector의 고정비율, 변수의 보여질 이름 등등.....

 

UPROPERTY(변수) 뿐만아니라 함수, 클래스, 구조체 인터페이스, Enum 마다 각 다른 MetaData가 있다

https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/GameplayArchitecture/Metadata/

 

 

...계속 추가중

 

  • 배열

선언 - typename Name [Size];

 

0부터 시작

 

 

배열의 이름은 수식에 사용시 자료형의 포인터 형으로 사용된다

자료형의 포인터 형으로 사용될 때 배열의 전체 주소가 아닌 첫번째 원소의 주소이다

arr1에 마우스를 가저다 대면 나오는 창, int* 라고 한다

 

이 때문에 배열과 배열의 대입이 이루어지지 않는다

 

그리고 여기에 얹어서 두가지 특징이 더 있는데

 

첫번째. 배열의 이름은값을 바꿀수 없는 상수(r-value)라는 점이다

 

두번째.  [0]번째 데이터의 주소와 배열 전체를 의미하는 주소는 같다

 


 

  • 문자열

연속되어 저장되어 있는 문자들

 

char text [10] = { 'a', 'b', 'c' }; // 는 a,b,c가 각 배열 인덱스에 복사되어 들어간다

char text [10] = "abc"          // 는 abc가 한번에 들어간다

 

char text [ ] = "abc" // 가 되는 이유는 초기 값을 정해주었기 때문

 

상수표현 " ~ "  -> 자료형이 const char *

 

문자열을 다룰때 끝을 알아야 그만큼 데이터를 사용할텐데 Null을 끝으로 인식하는 방법으로 사용한다

그렇기에 문자열상수( " ~ " )는 우리가 별도로 Null을 넣지 않아도 마지막에 Null이 자동으로 붙는다

그래서 Null이 붙은 크기가 고정되어야 문자열상수의 데이터를 온전히 사용할 수 있기 때문에

( " ~ " )는 const형이 붙어 문자열 상수라 한다

 ' ~ ' 와는 다를 수 밖에 없다

 

cout에서 char * 을 출력할때 다음주소를 한글자씩 출력하면서 Null을 찾는다

Null을 붙여주지 않아서 Null을 찾을때까지 출력하여 이상한 값이 나온다

 

 

char e = "a"; //불가능

char e = "abcd"; //불가능

char * e = "abcd"; //불가능

 

모두 대입하는 문자열 상수의 자료형[ const char * ]과 맞지 않다

마지막 불가능 코드는 "abcd"는 수정이 되지 않는 자료형인데 char * 은 수정이 가능한 자료형이다 그렇기에 대입 불가

 

입력 함수

cin = 화이트스페이스를 끝으로 간주 & 개행문자를 남김

※ 단 화이트스페이스, 개행문자가 제일 처음나오면 멀쩡한 문자가 나올때까지 무시

 

cin.get( ) = 개행문자를 끝으로 간주 & 개행문자를 남김 

cin.getline( ) = 개행문자를 끝으로 간주 & 개행문자를 읽고 폐기

 

strcpy = 문자열 복사

strcat = 문자열 추가

strlen = 데이터형의 길이가 아닌 문자열의 길이 반환

 

 


 

  • String

기존 C에서 Null 으로 마지막을 알아내는 방법과 달리

문자의 길이를 따로 저장하기에 Null관련 이슈가 없다

 

다만 실제로는 null로 끝나는 문자열과의 호환성을 위해 메모리상에 null을 포함하긴 한다

 

문자열 다루는 더 나은 방법의 클래스

 

들어오는 데이터에 따라 크기 자동 조절

 

배열처럼 인덱스 참조 가능

 

==, = , + , += 연산 가능

 

 

strncpy

strncat

.size( )

std::getline( ) - string용 getline


 

  • raw 문자열

문자열 하나하나가 모두 독립적인 문자열 (특수문자까지도)

 

R"~(   로 시작해서

)~"로 끝나야한다

 

 


 

많은 도움이 된 글

https://blog.naver.com/tipsware/221018307213

 

'문자열 상수'의 잘못된 사용에 대하여

C 언어 관련 전체 목차 : http://blog.naver.com/tipsware/221010831969 1. 배열로 선언된 변수의 초기화 ...

blog.naver.com

 

  • 식별자

"밑줄문자 두개"로 시작

"밑줄문자+대문자"로 시작

 

이 두가지는 예약어의 규칙에 속하기 때문에 훗날 문제가 될 수 도있으니

 

예약어 목록에 없다면 실행은되나 되도록 피하자

#include <iostream>

int main() {

	int __ABC = 3;
	int _Abc = 2;
	
	std::cout << __ABC << _Abc; //모두 출력 성공
	
	return 0;
}

 


 

  • 정수 자료형

소수부가 없는 자료형

 

char, short, int, long 같은 자료형, 크기는 컴파일러마다 다를 수 가 있다

 

 

※ 보통 8비트 = 1바이트 이지만 c++에서는 컴파일러의 기본 문자 세트를 수용할 수 있는 최소한의 비트수가 바이트!

ex) ASCII는 최소 8비트로 나타내므로 ASCII가 기본 문자 세트라면 8비트가 1바이트가 된다

 

정수 상수가 저장되는 자료형은 최소 int형이다

 

문자를 정수형으로 표현한다 (Char)

char형은 문자와 숫자를 저장한다

 

wchar_t형은 1바이트로 나타낼수 없는 문자를 위해 탄생

상수형은 접두사로 'L'이 붙는다

 


 

  • 멤버 연산자 (memvership operator)

객체의 멤버 사용할 경우 사용

 

ex) std::cout.puts(); 에서

1. " std::cout " // 2. " . "  // 3. " puts(); "

1.(객체)  2.(멤버연산)  3.멤버(함수)

 


 

  • const

상수, 값이 변화하지 않는다.

 

한마디로 데이터를 값이변하지않게 상수화 시킨다

 

그렇기에 무조건 선언과 동시에 정의로 초기화해야한다

[단 메모리에 올라갈때만 초기화 해주는듯 하다]

사용하지 않아 에러 X
바로 에러
해결

※클래스는 생성자에 이니셜라이저로 초기화, [ C++11 부터 바로 초기화 가능 ]

 

보통 관습으로 모두 대문자로 식별자를 만든다 

 

 

위치에 따라 상수화되는게 다르다!

const의 위치에 따라 어느게 상수화 되는지 달라진다

※ const int * == int const *

 

멤버 함수 한정으로 함수의 선언 뒤에 const를 붙일 수 있는데

붙이게 되면 함수 내에서 멤버변수를 변경할수 없게 만든다

접근지정자는 상관없다

 


 

  • 지수 표기법

ex) 314.234

가수부(기본값) 3.14234 // 지수부(스케일) E+3 ( 10의 3제곱이라는 뜻 )

=> 3.14234E+3  ( = 31.4234E+2 최종값이 똑같으면 가수부에 소수점을 어디에 찍든 상관없는듯하다 ) 

 

저장하는 방식은 위의 지수표기법과 비슷한데  [부호(0 or 1), 가수부(기본값), 지수부(스케일)]로 나누어 저장

 


 

  • 부동 소수점

부동자세의 움직이지 않는다는 느낌이 아닌

 

뜰 부, 움직일 동/ 공중에 떠서 (소수점이) 움직인다는 느낌 = 소수점을 움직이므로 여러 자리의 소수점을 표현 가능

 

※ 부동소수점 오차의 이유

https://ddidding.tistory.com/57

 


 

  • static_cast<> ()

자료형 변환

보통 형변환과 마찬가지로 사용한다고 데이터형이 영구적으로 바뀌는게 아니라 일시적이다

 

저렇게 상수를 포인터로 캐스팅하는건 안되나보다

 

주소연산자를 사용해서 다른 형의 주소로 캐스팅도 안된당

그냥 선형변환 후연산이 된다는 추가 사진


 

  • auto

"초기화 된 변수만" 자동으로 자료형을 추론해 정의해주는 키워드

 

편리하다! 하지만 아무곳이나 사용한다면 다른사람이나 훗날 코드를 본다면 욕나올듯

 

아직은 모르지만 나중에 복잡한 데이터형을 다룰때 가끔 사용할거같다

  • 전처리기 (preprocesser)

 

컴파일직전에 실행되는 프로그램

 

#으로 시작하여 줄바꿈으로 끝난다

 

 


 

  • name space

식별자의 영역을 생성

 

같은 식별자를 구분할수있게 해줌 & 확실한 출처의 식별자를 사용할수있게 한다

 

근데 중복정의가 가능한가보다

[ 하지만 식별자까지 중복은 불가능 ]

 

#include <iostream>

namespace AA {
	int a = 1;
}

namespace AA {
	int b = 2;
}

int main() {

	//실행가능
	std::cout << AA::b;
	
	return 0;
}

 

근데 내부에 중복으로 사용했을 경우 식별자까지 중복이 가능하다 ㅋㅋ [ 내부 중첩은  C++17부터 가능 ]

#include <iostream>

namespace AA {
	int a = 1;

	namespace AA {
		int a = 3;
	}
}

namespace AA {
	int b = 2;
}

int main() {

	std::cout << AA::a; // 1출력
	std::cout << AA::AA::a; // 3출력
	
	return 0;
}

 

namespace의 이름이 길다면 별명도 붙일수있다


using으로 간편하게 사용할수 있는데 using이 들어간 영역안에서만 유효하다

#include <iostream>

namespace AA {
	int myInt = 1;
}

void test() {

	//test()안에서만 AA를 사용시 정의를 하지 않아도 된다
	using namespace AA;

	//AA안에있는 myInt
	std::cout<< myInt;
}

int main() {

	//using namespace AA가 없으니 AA를 정의해줘야 한다

	std::cout << myInt; // 오류
	
	return 0;
}

using으로 간편하게 사용할수 있는데 using이 들어간 영역안에서만 유효하다

 

 

 


 

  • 함수 선언
//테스트 함수 선언
void A(int n) {

	std::cout << n;
}

int main() {

	A(5);

	return 0;
}

main에서 A가 호출되었을 때 일어난 일은

 

1. 함수 A시작 

 

2. 지역변수 n 생성

 

3. 지역변수 n에 5가 대입

 

이다. 

 

이걸 확실하게 알고있으면 나중 매개변수에 포인터 장난질 해놓은걸 덜 헤멜수있다

 

 


 

  • 키워드

특별한 의미가있는 미리 정해놓은 예약된 식별자,

 

사용자가 다른 의미로 사용할수 없다.

(단 사용 할 수 있는 언어도 있음 / C++은 X )

 

int for = 0;  // for도 키워드중 하나이기에 따로 사용 불가능

 

 

예약어라는 비슷한 개념도 있는데

 

키워드는 어떠한 사용의미를 지니고 있는 말이고

 

예약어는 사용하지 않지만 사용자에게 혼란을 막고

ex) java에서 const는 사용하지 않지만 예약어로 정해져있기에 사용 불가능하다 ( final사용 )

 

다음 버전이 업그레이드 될때의 사용하게 될지도 모르는 단어들을 미리 예약어로 정해놓아 사용못하게 해놓는다

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=youmasan&logNo=130025032660

 

 

 

이전글에서 이것까지 한번에 하려했지만 생각보다 뭐가 있어서 이어서 작성한다

 

이번 목표는 빨간사람(플레이어X)이 특정 공을 바라보면 된다

 

날 바라봐
빨간사람의 블루프린트 파트1

Get All Actors Of Class with Tag가 핵심이다

 

Tick 이벤트 = 단순 매 프레임 실행 이벤트

 

Get All Actors Of Class with Tag = 말그대로 특정태그가 달린 액터녀석들을 찾는다~ 이말이다

                                             Actor Class에서 자신이 찾고자하는 액터의 블루프린트클래스를 선택해준다

                                             Tag 에서 우리가 찾고자하는 액터에 붙여준 태그를 써준다

                                             [태그명은 자신이 맘대로 지정 - 밑에 태그 붙이는 법 있음]

                                             

                                             

 

For Each Loop = 배열내의 모든 인덱스를 타겟으로 실행시키는 루프, 예를 들어 인덱스가 3개인 배열이 들어왔다치면

                       0번 인덱스를 타겟으로 실행 -> 계속 노드를 물고물어 실행이 끝나면 ->

                       다시 이곳 For Each Loop으로 돌아와서 1번 인덱스를 타겟으로 실행 ····· 이런식이다

                       ArrayElement에서 각 인덱스 요소를 반환하고

                       Array Index에서는 인덱스(번호)를 int형으로 반환한다

                       Completed는 마지막 인덱스까지 모든 반복이 끝났을때 실행되는거 같다

 

 

 

그럼 이제 찾고자하는 액터에 태그를 붙여야한다

 

 

원하는 액터를 선택 후 디테일창에서 태그항목을 찾아 + 를 눌러준다

 

 

 

Look at me는 붙어있는게 아니라 단독적인 단순 TextRender이다

원래 None이라고 되어있는데 이곳이 태그의 이름이다 자신이 원하는대로 작성한다 그럼 완료

 

 

다시 블루프린트로 넘어와서

빨간사람 블루프린트 파트2

For Each Loop에서 나온 Array Element를 받아와 위치를 구해서 "바라보고싶은 액터를" "바라보는 회전값을" 구해 세팅

 

설명은 이전글에 되있을듯..?

 

 

최종본 Print String은 그냥 넣었다

 

 

 

이 Get All Actors Of Class with Tag는 같은 종류의 액터가 많을시에 태그를 붙여 쉽게 찾을수 있다

 

태그가 없는 버전인 Get All Actors Of Class 함수도 존재한다 이건 이름대로 모든 액터를 찾는거일듯 하다

 

 

근데 Get All Actors Of Class는 연산량이 많아 느려진다고 한다

 

그래서 저렇게 Tick을 이용하는건 비추천이다 한번 받아와 객체를 저장해서 사용하던지 해야겠다~

 

참고로 블루프린트가아닌 c++환경에서는 훨씬 괜찮은 함수가 있는거 같더라

+ Recent posts