8.Pointer(Dynamic Memory)
08 Sep 2019 | C++
Pointer
- 변수(Variable)가 무엇인가? 변수는 메모리 공간 이다. 컴퓨터에 꽃혀있는 RAM 내 어딘가를 의미한다. 그리고 RAM에 있는 메모리 공간에는 일련번호가 붙어있고, 모든 변수는 일련번호와 크기가 정해져있다. 단지 일련번호를 외워가며 프로그램을 작성할 수 없으니 일련번호와 이름을 비교하는 비교표를 컴파일러가 작성하고, 프로그래머는 그 비교표에 있는 이름을 외워서 프로그램을 작성하면 컴파일러가 나중에 이름을 일련변호로 변환하는 작업을 해준다.
- 포인터 역시 위에서 언급한 변수의 한 종류이다. 다른 변수와의 차이점이라면 위에서 말한 ‘메모리 공간의 일련번호’를 저장할 수 있는 변수다. 정수형 변수에는 정수값이, 부동소수형 변수에는 부동소수 값이, 그리고 포인터형 변수에는 ‘메모리 공간의 일련번호’가 저장된다.
- 즉 ‘포인터=메모리 공간의 일련번호’
- 그럼 메모리 공간의 일련본호 – 주소 따위를 저장해서 무엇에 쓰냐라는 문제가 대두 된다. 컴파일러가 알아서 이름을 주소로 바꾸어주는데 굳이 주소를 다루어야 할 필요가 있겠는가? 답은 보나마나 ‘물론’이다. 처음에 C라는 언어는 운영체제를 만들기 위해 만들어진 언어이며 하드웨어를 다루는데 가장 유리했던 언어이다. 포인터가 바로 그 ‘하드웨어를 다루는 힘’ 이다.
기본 포인터
- ‘변수=메모리 공간’이고 ‘포인터=메모리 공간의 주소를 저장하는 변수’이었으니, 결국 포인터는 ‘변수의 위치를 저장하는 변수’ 라는 의미가 된다.
- 아래 코드를 잠시 보자
#include <stdio.h>
int main (int argc, char * argv[])
{
int var = 10;
int *vp = &var;
printf("The value of pointer: %x\n", vp);
printf("The value before: %d, %d\n", var, *vp);
var = 20;
printf("The value after: %d, %d\n", var, *vp);
*vp = 30;
printf("The value then: %d, %d\n", var, *vp);
return 0;
}
- 5번 라인에서 vp라는 변수를 선언하면서 이름 앞에 (asterisk)가 붙어있는 걸 볼 수 있다. 실상 이 별표의 타입 일부로 ‘int (asterisk)’가 하나의 타입이 된다. ‘int (asterisk)’의 의미는 ‘정수값을 저장하는 메모리 공간의 주소를 저장할 수 있는 변수’이다. 다음과 같은 이유에 의해 ‘주소가 저장되는 변수’에도 불구하고 일반적인 변수의 타입이 추가로 붙는다.
- 변수에 타입이 있는 이유는 변수에 저장되어있는 데이터를 처리할 방법을 컴파일러에게 알려주기 위함이다
- 포인터 변수에 주소를 넣는 이유는 그 주소 자체가 필요 해서가 아니라 주소에 해당되는 메모리 공간에 저장되어있는 데이터가 필요해서 이다.
- 결국 포인터 변수에 타입이 존재하는 이유는 포인터 변수에 저장되어있는 주소위치에 있는 데이터를 처리할 방법을 컴파일러에게 알려주기 위함이다.
- 또한 5번 라인에서 vp에 값을 대입할 때 & 연산자를 사용하는 것을 볼 수 있다. &는 레퍼런스 연산자(reference operator)라 부르며, 변수의 주소를 알아내는데 사용된다. 결국 5번라인은 ‘정수형 포인터 vp를 만들고, var의 주소를 알아내서 vp에 저장한다’ 라는 의미가 된다.
- 반복해서 설명 되었듯이 포인터는 메모리 주소 - 메모리 공간의 일련번호 이다. 결국 vp에 저장되는 값은 실제로는 정수값 이다. 그렇기 때문에 7번라인에 보는 것 과 같이 그 값을 인쇄해 보면 정수값으로 인쇄된다.
- 8, 10, 12번 라인에 걸쳐서 변수 vp 앞에 * 연산자가 붙어있는 것을 볼 수 있다.[1] * 연산자는 포인터 연산자라고 하며, 포인터변수에 저장되어있는 메모리 주소에 해당되는 메모리 공간에 저장되어있는 값을 액세스 하려는 경우에 사용된다. 변수 vp에는 변수 var의 주소가 저장되어 있으므로 결국 (asterisk)vp를 통해 액세스되는 데이터는 var를 통해 액세스 되는 데이터와 동일하다. 9번과 11번 에서보면 var를 수정해서 보여지는 결과난 (asterisk)vp를 통해서 수정해서 보여지는 결과나 같은 것을 보면 유추가 가능할 것 이다.
Double Pointer
- consider this code
int i = 42;
int *pi = &i;
int **ppi = π
- As you can see, the variable “i” is an int which I’ve set to the value 42.
- pi is a pointer-to-int, which I’ve set to the address of i.
- ppi is a pointer-to-pointer-to-int, which I’ve set to the address of pi.
- So that’s all the double-asterisk means. It means “pointer-to-pointer”
- A pointer is a variable that holds a memory address. A pointer to a pointer simply holds the memory address of another pointer.
- In typical usage:
int i;
- This is called a “scalar” in computer science, which just means “an atomic quantity that can hold one value at a time”.
int *pi;
- This is typically an array of ints. That is, it is a variable that stores the memory location of a block of memory that stores a series of ints. Syntactically, the C++ language will let you treat pi as an array. Thus, you can write:
for (int x = 0; x < 10; ++x) pi[x] = x;
- This would store the values 0, 1, 2, 3, etc. in the first 10 spots of the memory block pointed to by pi.
- so then,
int **ppi;
- When you see this in code, it’s typically being used as a pointer to an array of pointers. In other words, a 2-dimensional array. It points to a block of memory that stores pointers, each of which points to a block of memory that stores ints. Again, C++ will let you treat it this way and write:
for (int x = 0; x < 10; ++x) {
for (int y = 0; y < 10; ++y) {
ppi[y][x] = 42;
}
}
- Conceptually, what this is doing is setting all of the cells in a 10x10 block of a matrix to the value 42.
- Now, having said all of that, you asked “what does it mean when passing….”
- Consider this:
void func ( int i ) {
// do something
}
- Obviously, that’s a function that takes an integer argument. Simple.
- Now this:
void func ( int *pi ) {
// do something
}
- Without anything else to go on but this function declaration, there are two possibilities:
- This is a function that takes an array of integers as an argument
- This is a function that takes an integer, passed by reference, as an argument.
- “Passed by reference” means that rather than merely(仅仅) passing a value to the function, I’m going to pass a pointer to (a.k.a. “reference to”) the value.d The reason to do this is so that the function will have the power to change the value.
- Here’s a super-simple usage that you might see:
private:
int _myData;
public:
void get_data ( int *pData ) {
*pData = _myData;
}
- When calling get_data, you’d pass it the address to the variable you want to store the data in, and the function would fill it in for you. That’s why you pass it by reference.
- Now we come at last to this:
void func ( int **ppi ) {
// do something
}
- What is this? Well, it’s either:
- A function that takes a 2-dimensional array (matrix) of integers as an argument, or
- A function that takes an array of integers, passed by reference, as an argument
- Once again, if it’s the latter, the reason would be that the function needs the ability to change the memory address the array points to — that is, point it somewhere else.
Example 1
#include <iostream>
using namespace std;
/* POINTERS ARE ordinary variables that can store addresses of variables */
int main()
{
int var = 5;
int a = 20;
cout << *&var << endl;
int * const p = &var; //that asterisk here is just used to INFORM about that this variable is a POINTER so it is a variable that can point to address of another variable
// p = &var;
cout << *p << endl; //that asterisk here is used to RETRIEVE (GET) value FROM indicated (pointed) area in our memory (address)
//*p = 20;
// var = 60;
*p = 60;
cout << "var: " << var << endl;
cout << "*p: "<< *p << endl;
cout << "a: "<< a << endl;
int * const p_const = &a; //this is a pointer that has to be initialized when defined, because it cannot change after defining the thing that it is pointing to (address)
const int * p_2 = &a; //this is a pointer that cannot change the value that is under address its pointing to.
const int * const p_3 = &a; //this is a pointer that cannot change the value that is under address its pointing to and also it cant change the address
cout << endl << endl << endl;
int ordinary_var = 10;
int *ordinary_p = &ordinary_var;
cout << "ordinary_var: " << ordinary_var << endl; //integer value
cout << "&ordinary_var: " << &ordinary_var << endl; //integer value
cout << "ordinary_p: " << ordinary_p << endl; //address
cout << "*ordinary_p: " << *ordinary_p << endl; //integer value from pointed place (ordinary_var)
cout << "&ordinary_p: " << &ordinary_p << endl; //address of pointer itself
int ** p_pointing_to_address_of_pointer = &ordinary_p;
cout << "p_pointing_to_address_of_pointer: " << p_pointing_to_address_of_pointer << endl;
return 0;
}
c_str()
- The basic_string::c_str() is a builtin function in C++ which returns a pointer to an array that contains a null-terminated sequence of characters representing the current value of the basic_string object. This array includes the same sequence of characters that make up the value of the basic_string object plus an additional terminating null-character at the end.
- Retrun Value : The function returns a constant Null terminated pointer to the character array storage of the string.
// C++ code for illustration of
// basic_string::c_str function
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main()
{
// declare a example string
string s1 = "GeeksForGeeks";
// check if the size of the string is same as the
// size of character pointer given by c_str
if (s1.size() == strlen(s1.c_str())) {
cout << "s1.size is equal to strlen(s1.c_str()) " << endl;
}
else {
cout << "s1.size is not equal to strlen(s1.c_str())" << endl;
}
// print the string
printf("%s \n", s1.c_str());
}
// C++ code for illustration of
// basic_string::c_str function
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main()
{
// declare a example string
string s1 = "Aditya";
// print the characters of the string
for (int i = 0; i < s1.length(); i++) {
cout << "The " << i + 1 << "th character of string " << s1
<< " is " << s1.c_str()[i] << endl;
}
}
Example 2
#include <iostream>
using namespace std;
int main()
{
string text = "this a test"; // t r a l a \0
/*
for (int i = 0; i < text.length(); i++)
{
cout << text[i] << endl;
}
*/
/* char ch = text[0];
// cout << ch << endl;
char characters[] = "123asdfasdfasdf4";
cout << characters[0] << endl;
cout << *(characters) << endl;
cout << characters[1] << endl;
cout << *(characters+1) << endl;
char *p = characters;
cout << p[0] << endl;
cout << *(p) << endl;
cout << p[1] << endl;
cout << *(p+1) << endl;
*/
const char * text2 = text.c_str();
cout << text2 << endl;
char array[] = "here is a text";
string test = array;
cout << test << endl;
const char * a = "this is a test 12512412";
cout << a[0] << endl;
char b[] = "this a test 124124";
b[0] ='g';
cout << b << endl;
char * const dynamic_array = new char[50];
dynamic_array[0] = 'k';
dynamic_array[1] = '\0';
//dynamic_array = "lalala";
cout << dynamic_array << endl;
delete [] dynamic_array;
string array_of_string[5] = "this i a text that will be in all of the elements of strings";
array_of_string[0] = "afsdf";
cout << array_of_string[0] << endl;
cout << array_of_string[1] << endl;
cout << array_of_string[2] << endl;
return 0;
}
Dynamic memory
- new는 힙에 메모리할당을 해주고 생성자를 호출 해주며 해당 타입으로 변환 까지 해주는 함수입니다.
- New 가 하는 일은
- 메모리 할당
- 생성자 호출
- 타입 변환
- Delete 가 하는 일은
- 소멸자 호출
- 메모리 해제
#include <iostream>
using namespaec std;
class Position
{
public:
Position() // 생성자
{
count << 2) new에 의해 생성자 호출됨 << endl;
}
~Position()
{
count << 3) Delete에 의해 소멸자 호출 됨 <<endl;
}
};
int main()
{
Position* prt = new Position();
count << 1) new 메모리 할당 끝 : 생성자 콜 << endl;
delete(prt); // 메모리 해제
return 0;
}
#include <iostream>
using namespace std;
/* dynamic allocation of memory */
int main()
{
// int var = 41240;
/*
int amount;
cout << "How many numbers would you like to store in an array? " << endl;
cin >> amount;
int *p = new (nothrow) int[amount];
if (p != NULL)
{
for (int i = 0; i < amount; i++)
{
cout << "Enter the " << (i+1) << " number: " << endl;
cin >> p[i];
}
for (int i = 0; i < amount; i++)
{
cout << "p [ " << i << " ] = " << p[i] << endl;
}
}
else
cout << "Not enough memory " << endl;
*/
{
int *p = new int;
cout << p << endl;
delete p;
p = new int;
cout << p << endl;
delete p;
}
//cout << "var: " << var << endl;
//delete []p;
return 0;
}
Example 3
#include <iostream>
using namespace std;
//void multiplyBy(int &, int);
int *multiplyBy(int *, int);
void multiplyArrayBy(int *, int, int);
int main()
{
int a = 10;
int *b = multiplyBy(&a, 5);
*b = 999;
cout << a << endl;
cout << *b << endl;
int array[10];
cout << sizeof(array)/sizeof(array[0]) << endl;
// 한 어레이에 4바이트 이니까 총 40바이트 하나당 4바이트를 나누면 10 개
for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
{
array[i] = i;
// cout << "array [" << i << "] = " << array[i] << endl;
}
multiplyArrayBy(&array[0], 5, sizeof(array)/sizeof(array[0])); // &array[0] == array
for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
{
cout << "array [" << i << "] = " << array[i] << endl;
}
return 0;
}
int *multiplyBy(int * var, int amount)
{
//int * var = &a;
*var = *var * amount;
return var;
}
void multiplyArrayBy(int *array, int amount, int sizeOfArray)
{
while(sizeOfArray--)
array[sizeOfArray] *= amount;
}
Example 4
#include <iostream>
#include <time.h>
using namespace std;
/* LOTTERY - pseudo-random numbers generator - drawing numbers */
void lottery(int, int);
int main()
{
// srand(time(NULL)); //seeds
// int nr = rand() % 49 + 1; //[1, 49]
// cout << nr << endl;
lottery(49, 6);
return 0;
}
void lottery(int total_balls, int balls_to_draw)
{
if (total_balls < balls_to_draw)
return;
srand(time(NULL)); //seeds
int *balls = new int[balls_to_draw];
for (int i = 0; i < balls_to_draw; i++)
{
balls[i] = rand() % total_balls + 1;
for (int j = 0; j < i + 1; j++)
{
if(balls[i] == balls[j] && i != j)
{
i--;
break;
}
else if (j == i)
cout << balls[i] << endl;
}
}
delete[] balls;
}
Example 5
#include <iostream>
using namespace std;
int main()
{
int a[3];
a[0] = 0;
a[1] = 20;
a[2] = 40;
short int zm;
int *const p = &a[0];
cout << p << endl;
cout << a << endl;
cout << endl << endl << endl;
cout << &a[0] << endl;
cout << &a[1] << endl;
cout << &a[2] << endl;
cout << endl << endl << endl;
cout << a << endl;
cout << a + 1 << endl;
cout << a + 2 << endl;
//this is kind of same as array a[0],a[1].a[2]
cout << endl << endl << endl;
cout << *a << endl;
cout << *(a + 1) << endl;
cout << *(a + 2) << endl;
cout << endl << endl << endl;
cout << a[0] << endl;
cout << a[1] << endl;
cout << a[2] << endl;
// cout << a++ << endl; // a++ a = a + 1
int * p2 = &a[0];
cout << *p2 << endl; // 0
cout << ++*p2 << endl; //1
cout << *++p2 << endl; //20
cout << *p2++ << endl; //20
cout << *p2 << endl; //40
return 0;
}
Static_cast<>
- explicit way in C++
#include <iostream>
using namespace std;
/* TYPE CASTING */
int main()
{
double var = 5.6;
int a = 5;
int b = 7;
cout << (double)a / b << endl;
cout << (int) var << endl; //explict way C
int x = 444;
short y = x; //implicit way of casting
cout << y << endl;
cout << int(var) << endl; //explict way C
cout << static_cast<int>(var) << endl; //explict way in C++
char ch;
cin >> ch;
cout << (int)ch << endl;
return 0;
}
COST의 활용
- const 키워드와 함께 정의한 변수의 값는 수정이 불가능하다. 즉 상수화 되어버리는데, 프로그래밍시에 바뀌어서는 안될값이 있을 경우 활용할 수 있다. 코드가 길어질 경우 실수로 변수의 값이 바뀌어 지는것을 방지할 수 있다.
Pointer
- 변수(Variable)가 무엇인가? 변수는 메모리 공간 이다. 컴퓨터에 꽃혀있는 RAM 내 어딘가를 의미한다. 그리고 RAM에 있는 메모리 공간에는 일련번호가 붙어있고, 모든 변수는 일련번호와 크기가 정해져있다. 단지 일련번호를 외워가며 프로그램을 작성할 수 없으니 일련번호와 이름을 비교하는 비교표를 컴파일러가 작성하고, 프로그래머는 그 비교표에 있는 이름을 외워서 프로그램을 작성하면 컴파일러가 나중에 이름을 일련변호로 변환하는 작업을 해준다.
- 포인터 역시 위에서 언급한 변수의 한 종류이다. 다른 변수와의 차이점이라면 위에서 말한 ‘메모리 공간의 일련번호’를 저장할 수 있는 변수다. 정수형 변수에는 정수값이, 부동소수형 변수에는 부동소수 값이, 그리고 포인터형 변수에는 ‘메모리 공간의 일련번호’가 저장된다.
- 즉 ‘포인터=메모리 공간의 일련번호’
- 그럼 메모리 공간의 일련본호 – 주소 따위를 저장해서 무엇에 쓰냐라는 문제가 대두 된다. 컴파일러가 알아서 이름을 주소로 바꾸어주는데 굳이 주소를 다루어야 할 필요가 있겠는가? 답은 보나마나 ‘물론’이다. 처음에 C라는 언어는 운영체제를 만들기 위해 만들어진 언어이며 하드웨어를 다루는데 가장 유리했던 언어이다. 포인터가 바로 그 ‘하드웨어를 다루는 힘’ 이다.
기본 포인터
- ‘변수=메모리 공간’이고 ‘포인터=메모리 공간의 주소를 저장하는 변수’이었으니, 결국 포인터는 ‘변수의 위치를 저장하는 변수’ 라는 의미가 된다.
- 아래 코드를 잠시 보자
#include <stdio.h>
int main (int argc, char * argv[])
{
int var = 10;
int *vp = &var;
printf("The value of pointer: %x\n", vp);
printf("The value before: %d, %d\n", var, *vp);
var = 20;
printf("The value after: %d, %d\n", var, *vp);
*vp = 30;
printf("The value then: %d, %d\n", var, *vp);
return 0;
}
- 5번 라인에서 vp라는 변수를 선언하면서 이름 앞에 (asterisk)가 붙어있는 걸 볼 수 있다. 실상 이 별표의 타입 일부로 ‘int (asterisk)’가 하나의 타입이 된다. ‘int (asterisk)’의 의미는 ‘정수값을 저장하는 메모리 공간의 주소를 저장할 수 있는 변수’이다. 다음과 같은 이유에 의해 ‘주소가 저장되는 변수’에도 불구하고 일반적인 변수의 타입이 추가로 붙는다.
- 변수에 타입이 있는 이유는 변수에 저장되어있는 데이터를 처리할 방법을 컴파일러에게 알려주기 위함이다
- 포인터 변수에 주소를 넣는 이유는 그 주소 자체가 필요 해서가 아니라 주소에 해당되는 메모리 공간에 저장되어있는 데이터가 필요해서 이다.
- 결국 포인터 변수에 타입이 존재하는 이유는 포인터 변수에 저장되어있는 주소위치에 있는 데이터를 처리할 방법을 컴파일러에게 알려주기 위함이다.
- 또한 5번 라인에서 vp에 값을 대입할 때 & 연산자를 사용하는 것을 볼 수 있다. &는 레퍼런스 연산자(reference operator)라 부르며, 변수의 주소를 알아내는데 사용된다. 결국 5번라인은 ‘정수형 포인터 vp를 만들고, var의 주소를 알아내서 vp에 저장한다’ 라는 의미가 된다.
- 반복해서 설명 되었듯이 포인터는 메모리 주소 - 메모리 공간의 일련번호 이다. 결국 vp에 저장되는 값은 실제로는 정수값 이다. 그렇기 때문에 7번라인에 보는 것 과 같이 그 값을 인쇄해 보면 정수값으로 인쇄된다.
- 8, 10, 12번 라인에 걸쳐서 변수 vp 앞에 * 연산자가 붙어있는 것을 볼 수 있다.[1] * 연산자는 포인터 연산자라고 하며, 포인터변수에 저장되어있는 메모리 주소에 해당되는 메모리 공간에 저장되어있는 값을 액세스 하려는 경우에 사용된다. 변수 vp에는 변수 var의 주소가 저장되어 있으므로 결국 (asterisk)vp를 통해 액세스되는 데이터는 var를 통해 액세스 되는 데이터와 동일하다. 9번과 11번 에서보면 var를 수정해서 보여지는 결과난 (asterisk)vp를 통해서 수정해서 보여지는 결과나 같은 것을 보면 유추가 가능할 것 이다.
Double Pointer
- consider this code
int i = 42;
int *pi = &i;
int **ppi = π
- As you can see, the variable “i” is an int which I’ve set to the value 42.
- pi is a pointer-to-int, which I’ve set to the address of i.
- ppi is a pointer-to-pointer-to-int, which I’ve set to the address of pi.
- So that’s all the double-asterisk means. It means “pointer-to-pointer”
- A pointer is a variable that holds a memory address. A pointer to a pointer simply holds the memory address of another pointer.
- In typical usage:
int i;
- This is called a “scalar” in computer science, which just means “an atomic quantity that can hold one value at a time”.
int *pi;
- This is typically an array of ints. That is, it is a variable that stores the memory location of a block of memory that stores a series of ints. Syntactically, the C++ language will let you treat pi as an array. Thus, you can write:
for (int x = 0; x < 10; ++x) pi[x] = x;
- This would store the values 0, 1, 2, 3, etc. in the first 10 spots of the memory block pointed to by pi.
- so then,
int **ppi;
- When you see this in code, it’s typically being used as a pointer to an array of pointers. In other words, a 2-dimensional array. It points to a block of memory that stores pointers, each of which points to a block of memory that stores ints. Again, C++ will let you treat it this way and write:
for (int x = 0; x < 10; ++x) { for (int y = 0; y < 10; ++y) { ppi[y][x] = 42; } }
- Conceptually, what this is doing is setting all of the cells in a 10x10 block of a matrix to the value 42.
- Now, having said all of that, you asked “what does it mean when passing….”
- Consider this:
void func ( int i ) { // do something }
- Obviously, that’s a function that takes an integer argument. Simple.
- Now this:
void func ( int *pi ) { // do something }
- Without anything else to go on but this function declaration, there are two possibilities:
- This is a function that takes an array of integers as an argument
- This is a function that takes an integer, passed by reference, as an argument.
- “Passed by reference” means that rather than merely(仅仅) passing a value to the function, I’m going to pass a pointer to (a.k.a. “reference to”) the value.d The reason to do this is so that the function will have the power to change the value.
- Here’s a super-simple usage that you might see:
private: int _myData; public: void get_data ( int *pData ) { *pData = _myData; }
- When calling get_data, you’d pass it the address to the variable you want to store the data in, and the function would fill it in for you. That’s why you pass it by reference.
- Now we come at last to this:
void func ( int **ppi ) { // do something }
- What is this? Well, it’s either:
- A function that takes a 2-dimensional array (matrix) of integers as an argument, or
- A function that takes an array of integers, passed by reference, as an argument
- Once again, if it’s the latter, the reason would be that the function needs the ability to change the memory address the array points to — that is, point it somewhere else.
Example 1
#include <iostream>
using namespace std;
/* POINTERS ARE ordinary variables that can store addresses of variables */
int main()
{
int var = 5;
int a = 20;
cout << *&var << endl;
int * const p = &var; //that asterisk here is just used to INFORM about that this variable is a POINTER so it is a variable that can point to address of another variable
// p = &var;
cout << *p << endl; //that asterisk here is used to RETRIEVE (GET) value FROM indicated (pointed) area in our memory (address)
//*p = 20;
// var = 60;
*p = 60;
cout << "var: " << var << endl;
cout << "*p: "<< *p << endl;
cout << "a: "<< a << endl;
int * const p_const = &a; //this is a pointer that has to be initialized when defined, because it cannot change after defining the thing that it is pointing to (address)
const int * p_2 = &a; //this is a pointer that cannot change the value that is under address its pointing to.
const int * const p_3 = &a; //this is a pointer that cannot change the value that is under address its pointing to and also it cant change the address
cout << endl << endl << endl;
int ordinary_var = 10;
int *ordinary_p = &ordinary_var;
cout << "ordinary_var: " << ordinary_var << endl; //integer value
cout << "&ordinary_var: " << &ordinary_var << endl; //integer value
cout << "ordinary_p: " << ordinary_p << endl; //address
cout << "*ordinary_p: " << *ordinary_p << endl; //integer value from pointed place (ordinary_var)
cout << "&ordinary_p: " << &ordinary_p << endl; //address of pointer itself
int ** p_pointing_to_address_of_pointer = &ordinary_p;
cout << "p_pointing_to_address_of_pointer: " << p_pointing_to_address_of_pointer << endl;
return 0;
}
c_str()
- The basic_string::c_str() is a builtin function in C++ which returns a pointer to an array that contains a null-terminated sequence of characters representing the current value of the basic_string object. This array includes the same sequence of characters that make up the value of the basic_string object plus an additional terminating null-character at the end.
- Retrun Value : The function returns a constant Null terminated pointer to the character array storage of the string.
// C++ code for illustration of
// basic_string::c_str function
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main()
{
// declare a example string
string s1 = "GeeksForGeeks";
// check if the size of the string is same as the
// size of character pointer given by c_str
if (s1.size() == strlen(s1.c_str())) {
cout << "s1.size is equal to strlen(s1.c_str()) " << endl;
}
else {
cout << "s1.size is not equal to strlen(s1.c_str())" << endl;
}
// print the string
printf("%s \n", s1.c_str());
}
// C++ code for illustration of
// basic_string::c_str function
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main()
{
// declare a example string
string s1 = "Aditya";
// print the characters of the string
for (int i = 0; i < s1.length(); i++) {
cout << "The " << i + 1 << "th character of string " << s1
<< " is " << s1.c_str()[i] << endl;
}
}
Example 2
#include <iostream>
using namespace std;
int main()
{
string text = "this a test"; // t r a l a \0
/*
for (int i = 0; i < text.length(); i++)
{
cout << text[i] << endl;
}
*/
/* char ch = text[0];
// cout << ch << endl;
char characters[] = "123asdfasdfasdf4";
cout << characters[0] << endl;
cout << *(characters) << endl;
cout << characters[1] << endl;
cout << *(characters+1) << endl;
char *p = characters;
cout << p[0] << endl;
cout << *(p) << endl;
cout << p[1] << endl;
cout << *(p+1) << endl;
*/
const char * text2 = text.c_str();
cout << text2 << endl;
char array[] = "here is a text";
string test = array;
cout << test << endl;
const char * a = "this is a test 12512412";
cout << a[0] << endl;
char b[] = "this a test 124124";
b[0] ='g';
cout << b << endl;
char * const dynamic_array = new char[50];
dynamic_array[0] = 'k';
dynamic_array[1] = '\0';
//dynamic_array = "lalala";
cout << dynamic_array << endl;
delete [] dynamic_array;
string array_of_string[5] = "this i a text that will be in all of the elements of strings";
array_of_string[0] = "afsdf";
cout << array_of_string[0] << endl;
cout << array_of_string[1] << endl;
cout << array_of_string[2] << endl;
return 0;
}
Dynamic memory
- new는 힙에 메모리할당을 해주고 생성자를 호출 해주며 해당 타입으로 변환 까지 해주는 함수입니다.
- New 가 하는 일은
- 메모리 할당
- 생성자 호출
- 타입 변환
- Delete 가 하는 일은
- 소멸자 호출
- 메모리 해제
#include <iostream>
using namespaec std;
class Position
{
public:
Position() // 생성자
{
count << 2) new에 의해 생성자 호출됨 << endl;
}
~Position()
{
count << 3) Delete에 의해 소멸자 호출 됨 <<endl;
}
};
int main()
{
Position* prt = new Position();
count << 1) new 메모리 할당 끝 : 생성자 콜 << endl;
delete(prt); // 메모리 해제
return 0;
}
#include <iostream>
using namespace std;
/* dynamic allocation of memory */
int main()
{
// int var = 41240;
/*
int amount;
cout << "How many numbers would you like to store in an array? " << endl;
cin >> amount;
int *p = new (nothrow) int[amount];
if (p != NULL)
{
for (int i = 0; i < amount; i++)
{
cout << "Enter the " << (i+1) << " number: " << endl;
cin >> p[i];
}
for (int i = 0; i < amount; i++)
{
cout << "p [ " << i << " ] = " << p[i] << endl;
}
}
else
cout << "Not enough memory " << endl;
*/
{
int *p = new int;
cout << p << endl;
delete p;
p = new int;
cout << p << endl;
delete p;
}
//cout << "var: " << var << endl;
//delete []p;
return 0;
}
Example 3
#include <iostream>
using namespace std;
//void multiplyBy(int &, int);
int *multiplyBy(int *, int);
void multiplyArrayBy(int *, int, int);
int main()
{
int a = 10;
int *b = multiplyBy(&a, 5);
*b = 999;
cout << a << endl;
cout << *b << endl;
int array[10];
cout << sizeof(array)/sizeof(array[0]) << endl;
// 한 어레이에 4바이트 이니까 총 40바이트 하나당 4바이트를 나누면 10 개
for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
{
array[i] = i;
// cout << "array [" << i << "] = " << array[i] << endl;
}
multiplyArrayBy(&array[0], 5, sizeof(array)/sizeof(array[0])); // &array[0] == array
for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
{
cout << "array [" << i << "] = " << array[i] << endl;
}
return 0;
}
int *multiplyBy(int * var, int amount)
{
//int * var = &a;
*var = *var * amount;
return var;
}
void multiplyArrayBy(int *array, int amount, int sizeOfArray)
{
while(sizeOfArray--)
array[sizeOfArray] *= amount;
}
Example 4
#include <iostream>
#include <time.h>
using namespace std;
/* LOTTERY - pseudo-random numbers generator - drawing numbers */
void lottery(int, int);
int main()
{
// srand(time(NULL)); //seeds
// int nr = rand() % 49 + 1; //[1, 49]
// cout << nr << endl;
lottery(49, 6);
return 0;
}
void lottery(int total_balls, int balls_to_draw)
{
if (total_balls < balls_to_draw)
return;
srand(time(NULL)); //seeds
int *balls = new int[balls_to_draw];
for (int i = 0; i < balls_to_draw; i++)
{
balls[i] = rand() % total_balls + 1;
for (int j = 0; j < i + 1; j++)
{
if(balls[i] == balls[j] && i != j)
{
i--;
break;
}
else if (j == i)
cout << balls[i] << endl;
}
}
delete[] balls;
}
Example 5
#include <iostream>
using namespace std;
int main()
{
int a[3];
a[0] = 0;
a[1] = 20;
a[2] = 40;
short int zm;
int *const p = &a[0];
cout << p << endl;
cout << a << endl;
cout << endl << endl << endl;
cout << &a[0] << endl;
cout << &a[1] << endl;
cout << &a[2] << endl;
cout << endl << endl << endl;
cout << a << endl;
cout << a + 1 << endl;
cout << a + 2 << endl;
//this is kind of same as array a[0],a[1].a[2]
cout << endl << endl << endl;
cout << *a << endl;
cout << *(a + 1) << endl;
cout << *(a + 2) << endl;
cout << endl << endl << endl;
cout << a[0] << endl;
cout << a[1] << endl;
cout << a[2] << endl;
// cout << a++ << endl; // a++ a = a + 1
int * p2 = &a[0];
cout << *p2 << endl; // 0
cout << ++*p2 << endl; //1
cout << *++p2 << endl; //20
cout << *p2++ << endl; //20
cout << *p2 << endl; //40
return 0;
}
Static_cast<>
- explicit way in C++
#include <iostream>
using namespace std;
/* TYPE CASTING */
int main()
{
double var = 5.6;
int a = 5;
int b = 7;
cout << (double)a / b << endl;
cout << (int) var << endl; //explict way C
int x = 444;
short y = x; //implicit way of casting
cout << y << endl;
cout << int(var) << endl; //explict way C
cout << static_cast<int>(var) << endl; //explict way in C++
char ch;
cin >> ch;
cout << (int)ch << endl;
return 0;
}
COST의 활용
- const 키워드와 함께 정의한 변수의 값는 수정이 불가능하다. 즉 상수화 되어버리는데, 프로그래밍시에 바뀌어서는 안될값이 있을 경우 활용할 수 있다. 코드가 길어질 경우 실수로 변수의 값이 바뀌어 지는것을 방지할 수 있다.
Comments