프로그래밍 공부

전체 글 700

카테고리 설명
프로그래밍 공부하는 블로그
  • 위 코드에서 ptr=NULL하지 않았고, 그럼으로인해 ptr에 남아있는 주소값이 임의의 메모리를 가리키게 되었음으로 유효하지 않는 메모리 주소를 가리키게 된다. 이를 Dangling Pointer 또는 Dangling Reference 라고 한다. 메모리를 해재 한 뒤. OS가 임의의 메모리공간으로 할당하여 사용하려고 할 때 주소값이 남아있음으로 코드 내에서 해당 주소로 접근이 가능해지기 때문에 심각한 보안 취약점으로 작용할 수 있다.

  • C와 C++의 메모리 동적할당을 알아보자. C에서 사용하는 메모리 동적할당은 다음과 같다. C언어에서는 malloc 과 calloc 그리고 realloc 을 사용하고, free를 통해서 동적할당된 변수를 날려줄 수 있다. 그러나 C언어에서의 동적할당은 free이후 메모리의 주소값이 들어있는 포인터를 NULL로 초기화 해주어야 했다. C++에서의 동적할당을 살펴보자. C++에서는 동적할당 시 C와 다르게 생성할 조건을 형변환 하지 않아도 자동으로 형변환 해주는 시스템을 가지고 있다. 다음을 살펴보자. delete 문을 사용하여 동적할당 된 포인터 변수를 초기화 해줄수 있고 따로 포인터변수를 NULL로 초기화 하지 않아도 된다. 그 외에도 해당되는 사이즈를 직접 초기화 해줄 수도 있다. new로 생성되는 동..

  • C++과 C는 배열 접근과 배열 생성방법이 조금씩 다르다. 예시를 살펴보자. 위의 예시와 같이, array 연산자를 사용하여 배열을 생성 할 수 있고, .at을 통해 접근이 가능하다. 위에 써놓은것 과 같이. at이 []보다 더 안정성이 높은데, 그 이유는,[]을 통해 접근하게되면, 범위를 벗어나도 접근이 가능하지만, .at으로 접근하게되면 범위를 벗어났을 시 밑과 같이 프로그램을 터트린다.

  • 시험 오답정리. 2. 다음 중 4byte 의 크기를 가지고 있는 자료형은? char long long float double short 4byte 크기의 자료형은 int, float, long 등이 있다. 여기선 flaot이 해당한다. 4444 5. 2Byte의 매모리에 23이 저장되는 bit 중 옳은 것은? 0101 1101 0001 0111 0000 0000 0110 1100 0000 0000 0101 1101 0000 0000 0001 0111 23을 2진수로 변환 시 0001 0111 그러나, 2byte = 16bit 임으로, 나머지 0으로 채움. 즉, 0000 0000 0001 0111 이다. 13. 다음 점프문중 반복중인 명령을 중단하고 조건식으로 다시 되돌아가는 명령어는 무엇입니까? cont..

  • C++에서도 메크로 펑션을 사용할 수 있다. #define에서 매크로를 선언하여 사용하는것 을 이야기 한다. 매크로 함수로 선언하면 CODE영역에서 함수를 저장하여 연산하기에 더 빠른 연산 처리가 가능하다. 코드 영역은 프로그램이 실행되기 전 코드 데이터가 들어가는 영역이다. 코드 예시와 실행 결과를 보자. 다음과 같은 방식으로 define을 사용하여 연산을 하는 펑션을 구축 가능하다. 그러나, 매크로 펑션은 입력된 매크로의 입력을 다음에 입력된 함수대로 변경되는것 이기에 괄호가 없어서 사용상 주의가 필요하다. 주의사항은 다음과 같다. 즉, 매크로로 변환하여 사용하는 것은 괄호가 들어가지 않아. 정상펑션 대로 사용하면, 1+2의 결과가 나온 3이 다음 1+2의 결과와 곱해져 9가 나와야하는것이, 1 + ..

  • c++에서는 iostream을 사용한다. 이것은 input_output_stream 이라는 입력과 출력의 함수를 사용하겠다. 라는 뜻 이다. C++에서는 C에서 사용하는.h같은 식으로 붙이지 않고, c에만 있는 함수를 사용하고 싶다면, c를 붙이고 사용하던 함수를 호출하면 된다. 예시를 보자.+ 출력문은 다음과 같다. 이는 출력문을 cout에 일정 문자열을 흘려보낸다 라는 뜻 이다. 위와 같이 사용할 수 있다. 변수를 선언하고 해당 변수를 출력할 수 도있다. std::cout로 데이터를 입출력 할 수 있다. 이것은 C++에서의 다양한 방법으로 입출력이 조정 가능하다. 위와 같이. 다양한 방법으로 입출력 변수를 조정할 수 있다. true로 나타낼 수 있고, false로 출력할 수 있고, 이것을 키고 끄면서..

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

위 코드에서 ptr=NULL하지 않았고, 그럼으로인해 ptr에 남아있는 주소값이 임의의 메모리를 가리키게 되었음으로

 

유효하지 않는 메모리 주소를 가리키게 된다.

 

이를 Dangling Pointer 또는 Dangling Reference 라고 한다.

 

메모리를 해재 한 뒤. OS가 임의의 메모리공간으로 할당하여 사용하려고 할 때 주소값이 남아있음으로 코드 내에서

해당 주소로 접근이 가능해지기 때문에 심각한 보안 취약점으로 작용할 수 있다.

 

위와같이 ptr1과 ptr2가 같은 주소를 가리킬때 ptr1에서 free 해버리면. ptr2는 허상 포인터가 되어버린다.

 

728x90

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

가변인자(variable argument)  (0) 2023.04.20
스택 프레임(Stack Frame)  (0) 2023.04.20
호출 스택 포인터(Call Stack Pointer)  (0) 2023.04.20
심볼 테이블 ( Symbol Table )  (0) 2023.04.19
L-value, R-value  (0) 2023.04.19
작성일
2023. 4. 14. 15:58
작성자
WDmil
728x90

C와 C++의 메모리 동적할당을 알아보자.

C에서 사용하는 메모리 동적할당은 다음과 같다.

malloc을 사용한 방식.

C언어에서는 malloc 과 calloc 그리고 realloc 을 사용하고, free를 통해서 동적할당된 변수를 날려줄 수 있다.

그러나 C언어에서의 동적할당은 free이후 메모리의 주소값이 들어있는 포인터를 NULL로 초기화 해주어야 했다.


C++에서의 동적할당을 살펴보자.

C++에서는 동적할당 시 C와 다르게 생성할 조건을 형변환 하지 않아도 자동으로 형변환 해주는 시스템을 가지고 있다. 다음을 살펴보자.

delete 문을 사용하여 동적할당 된 포인터 변수를 초기화 해줄수 있고 따로 포인터변수를 NULL로 초기화 하지 않아도 된다.

그 외에도 해당되는 사이즈를 직접 초기화 해줄 수도 있다.


new로 생성되는 동적배열을 2차원배열 처럼 사용해줄 수 도 있다.

int** ptrArr 로 new int*[5]를 생성하여. 5칸을 가진 한줄을 만들고.

각 칸마다 10개의 int칸을 동적배열로 생성하면. 5x10 2차원배열을 만들어서 사용할 수 있다.

 

그러나, 지울때 에는 역순으로. for문을 사용하여 53 - 54 줄 처럼 입력하여 지워주어야 한다.

 

그 후. 생성한 행 포인터를 delete 해야 완전하게 지워줄 수 있다.


malloc은 구조체에서 pod(plain old data 연속된 메모리) 타입을 인자로 받아와서 쓸 수 있다.

그러나, string, 함수 같은것은 pod타입이라서 malloc에서 사용할 수 없다.

 

new에서는 허용된다. 객체타입에 대한 동적 메모리할당을 지원하기 때문에, new는 객체 생성자를 호출하여 객체 탕비에 따라 필요한 메모리공간 을 자동으로 할당하고 객체 초기화를 수행한다.

 

또한, new는 malloc과 다르게. 생성과 동시에 할당된 메모리를 초기화해준다. malloc은 수동으로 초기화 해주어야 한다.

728x90
작성일
2023. 4. 13. 15:56
작성자
WDmil
728x90

C++과  C는 배열 접근과 배열 생성방법이 조금씩 다르다. 예시를 살펴보자.

위의 예시와 같이, array 연산자를 사용하여 배열을 생성 할 수 있고, .at을 통해 접근이 가능하다.

 

위에 써놓은것 과 같이. at이 []보다 더 안정성이 높은데, 그 이유는,[]을 통해 접근하게되면, 범위를 벗어나도 접근이 가능하지만, .at으로 접근하게되면 범위를 벗어났을 시 밑과 같이 프로그램을 터트린다.

 

728x90
작성일
2023. 4. 9. 03:10
작성자
WDmil
728x90

시험 오답정리.

2. 다음 중 4byte 의 크기를 가지고 있는 자료형은?

  1. char
  2. long long
  3. float
  4. double
  5. short

4byte 크기의 자료형은 int, float, long 등이 있다. 여기선 flaot이 해당한다.

 

4444

5. 2Byte의 매모리에 23이 저장되는 bit 중 옳은 것은?

  1. 0101 1101
  2. 0001 0111
  3. 0000 0000 0110 1100
  4. 0000 0000 0101 1101
  5. 0000 0000 0001 0111

23을 2진수로 변환 시 0001 0111 그러나, 2byte = 16bit 임으로, 나머지 0으로 채움. 즉,

0000 0000 0001 0111 이다.

 

13. 다음 점프문중 반복중인 명령을 중단하고 조건식으로 다시 되돌아가는 명령어는 무엇입니까?

  1. contunue;
  2. break;
  3. return;
  4. goto;
  5. do;

continue; continue는 선언 시, 현재 반복문의 가장 끝지점으로 이동한다. 물론, goto, 로도 가능하다.

 

20. int[4][3] 배열의 크기는 몇 Byte 입니까?

  1. 12
  2. 36
  3. 48
  4. 128
  5. 256

int 자료형은 대부분 4byte. 4 * 3 * 4 = 48. 48byte 이다.

 

22. 다음 중 매개변수를 통해 넘긴 공간의 값을 수정할 수 있는 것은?

  1. void Change(int num);
  2. void Change(const int num);
  3. void Change(const int* num);
  4. void Change(int* const num);
  5. void Change(const int * const num);

1. 매개변수 자체가 전달. 펑션 종료 시 데이터가 날아감으로 반영되지 않음.

2. const int 로 선언되어 상수처리 되기에 매개변수 num을 변환할 수 없음.

3. int* 이지만, const int* 임으로 포인터가 가리키는 데이터를 변경할 수 없음.

4. const num 이지만, int*자체에 상수처리된 것 이 아니기 때문에, 주소는 변경 불가능 하나, 주소의 데이터는 변경 가능.

5. const int* 이기에 가리키는 데이터 변경 불가능, const num 이기에 주소값도 변경 불가능.

 

23. 64bit 체제의 프로그램에서 포인터의 크기는?

  1. 2Byte
  2. 4Byte
  3. 6Byte
  4. 8Byte
  5. 16Byte

32Bit체제는 32/8 로 4Byte의 크기의 주소값을 가지며, 64Bit체제는 64/8로 8Byte의 크기의 주소값을 가진다.

 

25. 배열 int Array[5] 의 시작 주소가 80 일 때  Array + 4 의 주소인 것은?

  1. 80
  2. 84
  3. 88
  4. 92
  5. 96

int = 4byte로 연산할 시, Array[0] 부터 Array[4]까지 진행함으로, 5번째 열의 시작주소를 확인하면 된다.

Array[0] = 80, Array[1] = 84, Array[2] = 88, Array[3] = 92, Array[4] = 96

 

26. 배열 float Array[5]의 시작주소가 100 일 때 값이 다른 것 은?

  1. &(Array[3])
  2. Array + 3
  3. 112
  4. &*(Array + 3)
  5. &(*Array + 3)

&(Array[3]) = 100 + (3*sizeof(float)) = 112 float는 4byte이다.

Array + 3 = 100 + (3*sizeof(float)) = 112

112 = 112

&*(Array + 3) = 2번 항에 포인터 주소를 붙인것 임으로 112 와 같다.

&(*Array + 3), *Array = 100 &(100+3) 임으로, 100번지이다. 값이 변한거지 주소가 참조되지 않았다.

 

28. 다음 중 컴파일러가 수행하는 일이 아닌것은?

  1. 소스코드를 기계어로 변환
  2. 컴파일링 에러 확인
  3. 일으킨 문제의 소스코드 라인 지시
  4. 파일 참조 오류 반환
  5. 실행 도중 에러에 대한 반환

실행 도중 에러에 대한 반환은 컴파일러가 아닌 운영체제가 처리한다.

 

30. 다음 중 arr[1][0]을 가리키지 않는 것은?

  1. arr + 1
  2. &arr[1]
  3. &arr[0] + 1
  4. &arr[1][0]
  5. *(arr[0] + 1)

arr + 1 = arr[1]의 시작주소 의미, arr[1][0]을 가리킨다.

&arr[1] : arr[1]의 시작주소 의미, arr[1][0]과 동일한 값을 가짐.

&arr[0] + 1 : arr[1]의 시작주소를 의미, arr[1][0]을 가리키거나 값을 가짐,

&arr[1][0] : arr[1][0]의 주소를 의미한다. arr[1][0]을 직접 가리키는 주소,

*(arr[0] + 1) : arr[0]의 두번째 요소인 arr[0][1]을 의미, arr[1][0]과는 관련 없음.

 

33. int arr[3] = {1, 2, 3}; 을 ptr이라는 포인터 변수에 저장할 때, ptr이 가리키는 값도, ptr이 가리키는 주소 값 도 변경할 수 없도록 하는 코드를 작성하시오.

  • const int* const ptr = arr;

 

41. 보기와 같이 구조체를 동적 할당할 때 맴버의 접근 방법 중 옳은 것은?

보기 ) Struct* p = (Struct*)malloc(sizeof(Struct)*5);

  1. p.member;
  2. p[0]->member
  3. (*p)->member;
  4. *(p + 1).member;
  5. *(p[1])->member;

1번은 구조체가 아니라 포인터 이기 때문에 -> 로 접근해야한다.

2번은 p가 구조체 배열을 가리키지만, -> 연산자는 []와 같이 사용할 수 없다. 이미 첫번째 구조체를 참조하기 때문이다.  -> 가 아니라 . 으로 바꾸어야한다.

3번은 *p가 이미 첫번째 구조체를 참조함으로 . 연산자를 사용하여야 한다.

4번은  포인터 변수 임으로 *(p + 1) -> member 가 되어야 한다.

5번은 member가 포인터 라면, 올바른 접근방법이다. member가 포인터 인지 아닌지가 불분명하다.

 

42. const int * p 의 설명으로 옳지 않은 것은?

  1. p 가 가리키고 있는 변수의 값의 수정이 불가능하다.
  2. p 가 가리키고 있는 주소의 변경이 가능하다.
  3. p 가 가리키고 있는 변수의 값에 접근이 불가능하다.
  4. p를 통하여 다른 변수를 가리킬 수 있게 수정이 가능하다.
  5. p는 자기 자신만의 주소를 가지고 있다.

const 임으로 변경은 불가능하나, 접근은 가능하다.

 

47. const 키워드에 대해 옳지 않은 것은?

  1. 기본 자료형에 사용할 수 있다.
  2. 매개변수에 사용할 수 있다.
  3. 구조체에 사용할 수 있다.
  4. 선언 시 초기화가 이루어져야 한다.
  5. 함수의 반환형으로 사용할 수 있다.

함수의 반환형으로 사용할 수 없다. C++에서는 선언 시 초기화가 이루어져야 선언된다. 그렇지 않으면 선언 될 수 없다.

 

50. 다음 코드의 출력 결과를 적으시오,

 

int arr[2][3] = {1, 2, 3, 4, 5, 6}

int(*p)[3] = NULL;

 

p = arr;

 

printf("%d\n", *(p[0] + 1) + *(p[1] + 2));

2,6

printf("%d\n", *(*(p+1)+0)+*(*(p + 1) + 1));

4,5

답 : 

8

9

728x90
작성일
2023. 4. 6. 15:51
작성자
WDmil
728x90

C++에서도 메크로 펑션을 사용할 수 있다. #define에서 매크로를 선언하여 사용하는것 을 이야기 한다.

매크로 함수로 선언하면  CODE영역에서 함수를 저장하여 연산하기에 더 빠른 연산 처리가 가능하다.

 

코드 영역은 프로그램이 실행되기 전 코드 데이터가 들어가는 영역이다.

코드 예시와 실행 결과를 보자.

다음과 같은 방식으로 define을 사용하여 연산을 하는 펑션을 구축 가능하다.


그러나, 매크로 펑션은 입력된 매크로의 입력을 다음에 입력된 함수대로 변경되는것 이기에

괄호가 없어서 사용상 주의가 필요하다. 주의사항은 다음과 같다.

결과

즉, 매크로로 변환하여 사용하는 것은 괄호가 들어가지 않아. 정상펑션 대로 사용하면, 1+2의 결과가 나온 3이 다음 1+2의 결과와 곱해져 9가 나와야하는것이, 1 + 2 * 1 + 2 가 되어, 의도와는 다른 결과가 나타나는 것을 확인할 수 있다.

 

이와같은 괄호문제로 인하여, 매크로 펑션을 사용할 때 에는 함수의 연산 간, 우선순위를 잘 살펴보는것 이 중요하다.

 

그리하여, 원하는대로 9라는 출력값을 나타내기 위해서는 다음과 같이 작성해야 한다.

즉, 연산 결과가 함수펑션에서 나타나는 것 이 아닌, 수학연산 자체를 코드에서 실행한다고 이해해도 무방하다.

 

이를 다른 방법으로 응용하면 다음과 같이 최대값 구하는 함수 또한 define으로 제작이 가능하다.

이는 다음 함수와 같은 효과를 보면서도, 연산을 펑션에서 하는것 이 아닌 코드 자체에서 끌어와서 연산하기에 더 빠른 연산을 보장한다.


만약, 펑션단위로 작성하면서 함수펑션과 같은 효과를 보고싶을 경우가 있을 것 이다.

이럴경우 코드자체에 펑션을 남기기 위해 다음과 같이 코드를 작성하면 된다.

위와 같이 작성하면, 작성한 펑션 또한 함수펑션과 같은 동작속도를 발휘할 수 있다.


C언어에서는 변수에 데이터를 입력받아오는 과정에서 int나 flaot 또는 double같은 변수형 선언을 한 뒤 받아와야한다.

그러나, C++에서는 그러한 번거로운 선언대신 auto라는 방법을 사용할 수 있다. 다음과 같은 예시를 살펴보자.

위와 같이 int형과 float형 double형을 선언하여 덧샘결과를 result에 넣어준다는 가정을 해보자,

그렇다면 auto result는 a와 b형을 더하면서, 형변환을 시도한다.

가장 우선순위가 높은 변수를 기준으로 형 변환을 하여 덧셈 결과를 출력하고 형변환을 한다.

 

이 우선순위 는 다음과 같이 int < float < double 처럼 쉽게 생각하면, 덧셈을 하였을 때 형변환을 하여도, 잘라 없어지는 수의 단위가 작은 순서대로 형변환을 하여 데이터를 절삭한다 라고 생각하면 된다.


펑션을 선언하고, 펑션에도  auto를 넣어줄 수 있다. 리턴값을 정해주지 않고, 나중에 return을 사용자 임의로 줄 수 있기 때문에 편리하게 코드를 작성할 수 있다.

또한 꼬리표를 달아줄 수 있는데, 앞에 auto를 넣어놓고 코드를 마무리 한 뒤, 코드의 리턴값이 int나 float로 정해진것을 프로그래머가 확인하였을 때, 꼬리표로 int를 붙여주면, auto가 형을 찾을 필요가 없이 int로 지정되어 더 빠르게 설정이 가능하다.

 

쉽게 생각하면, auto는 코드 작성 시작시에 작성하는 것 이고, return은 결국 나중에라도 결정될 수 있기에 프로그래머 의 편리함이 더 늘어나는것 이다. 마지막에 int나 float을 바꾸어주면되고, 수정도 편하게 할 수 있을것이다. 

[ int를 리턴시켜도 float으로 받아와야할 수도 있다! ]


그러나, 펑션의 매게변수는 auto로 지정해줄 수 없다. 이는 펑션의 설계자체에 문제가 되는데, C++에서는 펑션을 찾을 때 펑션의 이름이 아닌 펑션의 매개변수를 기준으로 찾게된다. 이때 auto로 펑션을 지정해놓으면, 이름이 겹치는 펑션을 여러개 작성해놓았을 때 모호 문제가 발생할 수 있음으로, auto는 허용하지 않는다.


C++은 C와 다르게 같은 이름의 함수를 여러개 사용할 수 있다.

그러나, 유의해야 하는 점 은 함수를 선언할 때 매개변수를 다르게 해야한다. 매개변수가 같다면, 호출시 두개의 함수를 동시에 호출하기 때문에 모호성 문제가 발생한다.

 

그럼으로 같은 이름의 함수를 사용할 때 에는 매개변수를 다르게 하는것 이 중요하다. 다음과 같은 예시를 보면 알 수 있다.

위와 같이 함수의 이름을 중복하여 사용할 수 있다. 그러나, 매개변수로 구분해야만 한다.

또는, 인자의 개수를 다르게 하여 구분할 수 도 있다.

사용예시는 다음과 같다.

 

사용시에 리턴값이 달라질 수 있음으로, auto를 사용하면 임의의 리턴값을 판단하여 자동으로 분류해줌으로 더 편하게 사용할 수 있다.


함수를 선언 시 매개변수를 다르게 하였음에도 모호성 문제가 발생하는 경우가 있다. 이는 다음과 같다.

위와 같은 방식으로 output 함수를 생성하고, 각각 다른 int, unsinged int, float 으로 구성된 함수를 만들었다는 가정 하에

함수를 호출 시 int와 unsigned int를 구분하지 못해 모호성 문제가 발생한다.

30번째 줄 을 실행 시 output 1을 호출하나, int와 unsinged int 두개 전부 해당됨 으로 모호성 문재가 발생한다. 이를 유의하여 사용하여야 한다.


자신과 일치하는 변수를 찾지 못했을 경우, 가장 적합한 변수로 형변환하여 찾게된다.

예시는 다음과 같다.

output에는 char문이 없다.

output에는 char문이 없음으로, char를 받아올 수 없다. 그러나, 형변환 하여 손상이 가장 적은 변수로 형변환하여 데이터를 받아들이게 된다. 즉, int로 형변환하여 받아들인다.


함수를 선언할 때 매개변수 를 입력하지 않았다면, 매개변수 의 기본값을 입력해줄 수 있다.

이는 C++는 C와 다르게 함수명이 아닌 매개변수 를 기준으로 함수를 찾기 때문에 가능하다. 예시는 다음과 같다.

그러나, 같은 함수이름을 사용하는 중첩방식과 기본매개변수를 같이 사용하는것은 권장되는 방식이 아니다. 그 이유는 다음과 같다.

26번째 줄 과같이 2를 넣고 선언하였을 경우, 컴퓨터는 print(int x = 7) 의 x에 2를 넣은것 인지, print(int x, int y = 7)의 x에 2를 넣은것 인지 판단할 수 없음으로 모호성 문재를 발생시킨다. 그렇게 됨으로써 오류가 발생할 수 있으니, 이와같은 방법은 

 

권장되는 방법이 아니다. 그럼으로 유의해서 사용해야 한다.


또한, 앞의 값을 기본값으로 사용하고 뒤의값을 변경하고 싶어도 앞의값을 무시한 채로 사용할 수 없다.

앞의 값을 그대로 10으로 사용하고 z의 값만 3으로 바꾸고 싶다고 하더라도, test에 3만 넣는것으로 바꿀 수 없다.

다른 모든 값을 채워넣고 가장 마지막값을 변경해야 마지막값을 변경할 수 있다.


C++은 C와 다르게 문장을 출력하거나 수정할 때 배열참조방식을 사용하지 않아도 된다. 이는 다음과 같다.

14번째 줄은 const를 빼면 C++에서는 허용하지 않는다. 어차피 상수항이기 떄문에 수정이 불가능하여 const를 붙여야 하게 제한한다.

C는 위와 같은 방식을 사용하여 배열에 문자를 하나씩 넣는방식으로 데이터를 참조하여 출력할 수 있다.

 

C++에서는 다른방법인 string을 사용한다. 다음 예시를 살펴보자.

위와 같이. string을 사용하여 문장을 만들어서 넣어줄 수 있고, 각각의 문장을 하나로 결합하여 출력해줄 수 도 있다.

또한, += 연산을 사용하여 문장 끝에 다른 문장을 붙여넣어줄 수 도 있다.

 

그렇다고 C처럼 배열연산을 못하는것 도 아니라서, 배열처럼 사용또한 가능하다.


C++에서의 포인터연산은 C와 비슷한 방식으로 이루어지나, 변수초기화방법을 C++방식을 따르게 된다.

예시는 다음과 같다.

nullptr_t 를 사용하면 포인터를 nul로 초기화할 수 있다.


C++은 C와 다른방식의 랜덤함수 호출을 사용한다.

C에서의 랜덤함수 호출을 먼저 살펴보자.

위와 같은 방식으로 랜덤함수를 불러와서, srand로 초기화하고 시간상수를 받아다가 시드로 사용한 뒤 10개의 랜덤수를 0~ 9 까지 출력하는 코드 이다.

 

이를 C++로 다시 살펴보자.

다음과 같은 방법으로 함수를 호출하고 출력하게 된다. random_device 라는 함수를 호출하고 

rd 라는 변수에 0 ~ 2^32 수 사이의 범위 내에서의 시드를 생성하게 된다.

 

mt19937 는 메르센 트위스터 유사난수생성기 중 하나로, 1997년 마츠모토 마코토와 니시무라 다쿠지가 개발한 난수 생성기 이다. 기존 생성기를 개선하고, 질이 좋은 난수를 생성하며, 속도또한 빠르기 때문에 다양한 분야에서의 난수를 생성하기 위해 사용한다.

 

mt19937의 특징은, 2^19937-1의 주기를 623차원 내에 고르게 분포시켰다는것 에 있다.

쉽게 말하면, 2^19937 - 1 의 범위수를 생성해내는데 난수를 623개까지 생성한 뒤 하이퍼큐브 좌표에 입력하여 좌표점을 찍어도, 유사성을 발견할 수 없다는 의미이다.

 

또한 이를 비트연산 으로 알고리즘을 구현하였기 때문에, 속도도 매우 빠르다.

 

즉, 위 코드를 분리하면,

random_device 라이브러리 에서 rd라는 임의 하드웨어의 난수를 가져온 다음,

mt19937 클래스의 객체 messenne 를 생성하며, rd값을 시드로 받아와 사용한다.

그 후, uniform_int_destribution<>에서 reNUJm의 범위를 지정하여, 일정 수 내의 범위 의 수 가 생성되도록 재한한다.

그리고 26번째의 함수를 사용하여. 생성된 난수를 사용하여, 범위 내의 랜덤 수를 생성하게 된다.

 

 

 

 

728x90
작성일
2023. 4. 5. 15:57
작성자
WDmil
728x90

c++에서는 iostream을 사용한다. 이것은 input_output_stream 이라는 입력과 출력의 함수를 사용하겠다. 라는 뜻 이다.

C++에서는 C에서 사용하는.h같은 식으로 붙이지 않고, c에만 있는 함수를 사용하고 싶다면, c를 붙이고 사용하던 함수를 호출하면 된다.

 

예시를 보자.+

 

출력문은 다음과 같다.

이는 출력문을 cout에 일정 문자열을 흘려보낸다 라는 뜻 이다.

위와 같이 사용할 수 있다.


변수를 선언하고 해당 변수를 출력할 수 도있다.


std::cout로 데이터를 입출력 할 수 있다.

이것은 C++에서의 다양한 방법으로 입출력이 조정 가능하다.

위와 같이. 다양한 방법으로 입출력 변수를 조정할 수 있다.

true로 나타낼 수 있고, false로 출력할 수 있고, 이것을 키고 끄면서 원할때 다양한 변수를 출력하는걸 더 많은 코드를 귀찮게 더 넣지 않고도 가능하다.

 

데이터의 변수를 진수형태로 출력하는것또한 같은 방법으로 가능하다.

 

단, printf와 같은 방법으로 데이터를 출력하는 것이 아님으로, %d와 같은 형변환을 이루어주지 않아도 데이터의 형을 직접 확인하여 출력해 준다.


변수를 초기화 하는방법또한 c언어와 C++은 다르다, 다음 예시를 살펴보자.

 C++은 변수를 초기화 하는 방법이 3가지 존재한다.

x에 10을 복사해서 넣는 6번째줄의 copy initalization

y에 10을 직접넣어주는 7번째 줄의 direct initialization

z에 10을 배열의 1칸처럼 넣어주는 uniform initialization

의 3가지 방법이 있다.

 

각각의 변수 초기화 방법은 6줄은 c의 방법, 나머지는 C++에서 추가된 방법이다. 그중 direct 초기화가 가장 빠르다.

안정성이 가장 높은건 uniform이 가장 높다.


변수를 c와 같이 int형에 float형을 넣어서 데이터 초기화를 하면

일정의 넣을 수 없는 데이터가 잘리는 현상이 나타나는데, 이것을 C++방식대로 넣을경우  error가 나타나게 된다. 다음 예시를 살펴보자.

위와 같이 error 가 나타나는것을 볼 수 있다.

C++에서는 데이터를 변환할 수 없을경우 err가 나타난다.

C++로 와서 새로 생긴 데이터입력 방식으로는 값을 벗어나는 입력을 넣을 수 없다.


데이터의 형에 따른 최소값과 최대값을 numeric_limits를 통해 출력 할 수 있다.

numeric_limits<형> 형을 통해 데이터타입을 입력하여 데이터타입의 max와 min을 출력할 수 있다. 

20번줄을 해석하면 다음과 같다.

std의 cout를 호출, 그 내부의 std에 numeric_limits를 가져와 short를 입력, 그 안의 max를 출력. 그후 std의 endl를 호출


C언어와 마찬가지로 데이터의 형 변환을 할 수 있다. 방법은 다음과 같다.

각각 형변환의 방법은 3가지가 있다.

우선 첫번째 는 해당된 데이터를 그냥 출력하는것,

 

34번째 줄은 C언어의 방식대로 강제적인 형변환을 시도한다. 어떠한경우에도 형변환을 해주기 때문에 가장 힘이 강하다. 그러나, 오류가 나올 가능성이 있다.

 

35번째 줄은 C++방식대로의 스타일이다. 34번째와 다르게 k를 괄호로 감싸는 걸 볼 수 있다. k를 int형으로 넣는다고 보면 된다. 동작방식은 같으나, C++형태의 스타일이다.

 

36번째 줄은 C++방식이나, 더 안정적인 방법이다. 35번째와 다르게 static_cast<>를 사용하는것 을 볼 수 있는데, 이것은 형변환이 가능할 경우 에만 형변환을 시도해준다. 그리하여 오류가 날 가능성이 더 적어지는 효과가 있다.

 


C언어의 const는 연산자를 상수로 처리해주는 것이다.

변수를 변환하지 못하는 상수로 바꿔주는 효과가 있는데, 이것은 Define과 같은 효과를 가진다. 그러나 Define과는 다르게 런타임 시 값이 정해지는 차이가 있다.

 

C++에서는 constexpr이라는 방법을 사용할 수 있다. 다음 예시를 보자.

원래 배열선언시 런타임 때 선언되는 상수로는 사용할 수 없음을 볼 수 있다. 그렇기 때문에 정해진 데이터값으로 변수를 넣어주어야 하나, constexpr을 사용할 경우 컴파일 시 데이터가 정해지기 때문에 순서상 배열값에 넣을 수 있다.

그럼으로 일반적인 배열값을 더 효율적으로 넣어줄 수 있다.


Namespace라는 것 이 있다.

이것은 펑션을 따로 정의해주는 함수처럼 어떠한 변수들이나 함수를 이름공간으로 정의해서 하나의 그룹으로 묶어주는것을 이야기한다. 

 

이러한 Namespace방법은 여러명이 다양한 코드를 작성하여 하나로 합칠 때 동일한 변수를 사용하였을 경우, 모호성 문제가 생기는것을 방지해주는 역활을 한다.

즉, 변수이름이 겹쳐서 코드에 에러가 나는 경우가 있는데. 그것을 사전에 차단해준다.

다음 예시를 살펴보자.

위와 같은 방식으로 namespace를 정의하여 변수를 정의해줄 수 있음을 볼 수 있다. 다음 함수를 호출하거나 변수를 호출하기 위해서는 밑과 같은 방식을 따른다.

다음과 같은 namespace방법을 사용하여 변수를 출력해줄 수 있다.

 

62번째 줄의 경우 A에 접속하여 exFunc를 출력한다는 말이다.

63번째 줄의 경우 B에 접속하여 exFunc를 출력한다는 말이다.

 

65번째 줄을 해석하면, myNamespace1을 호출, 그 안의 AA를 호출하고 그 안의 BB를, CC를, 그 안의 c를 호출한다는 의미이다.

 

그럼으로 다음 Namespace를 호출하면 c를 다룰 수 있다.

 

myNamespace2::a = 20;을 호출하여 a를 20으로 바꿔줄 수도 있다.


만약 std를 호출하지 않고도 더 빠르게 코드를 호출하기 위해서는 다음과 같은 방법을 사용할 수 있다.

using std::cin을 넣으면 cin을 사용할때, cout을 넣으면 cout를 사용할때, endl를 넣을때 등 std를 다시 선언하지 않아도 된다.

이는 해석하면, cin을 사용할때, cout를 사용할 때, endl를 사용할 때 str에 있는걸 무조건 사용하겠다. 라는 말이다.

 

80번째 줄을 보면, using namespace std를 볼 수 있는데, 이것은 std라는 namespace에 있는 모든 함수, 변수가 선언되었을 경우 무조건 std에 있는것을 사용한 것 처럼 취급한다는 의미 이다.

 

그리하여 , 위 코드를 선언하면 87번처럼 작성하여도 출력이 가능하다.


그러나, 변수명이 그 내부 main에 선언되었을 경우 또는 전역변수가 같은 변수명 일 경우, 같은 변수가 std와 main문에 있을경우 변수는 무조건 main문에 있는 변수가 우선되어 작성된다. 그럼으로 해당 변수에 1을 더하면 1이 더해져서 출력됨을 볼 수 있다.


만약 전역 변수에 더하고 싶다면, 90번째줄 처럼 작성해주면 된다.

그러면 전역변수에 접근하고 출력해줄 수 있다.

728x90