변수 범위와 더 다양한 변수형

윤형찬·2020년 10월 26일
0

C++

목록 보기
4/10
post-thumbnail

지역 변수의 범위(Scope), 지속기간(Duration)

  • ??
  • 설명,,,
#include <iostream>

int main()
{
	using namespace std;

	int apple = 5;

	cout << apple << endl;
	{
		cout << apple << endl;
		int apple = 1;
		cout << apple << endl;
	}
	cout << apple << endl;
	
	return 0;
}

5
5
1
5



전역 변수, 정적 변수, 내부 연결, 외부 연결

  • 전역 변수
    - 일반적으로 main 함수 밖에 선언해둔 변수
    - 전역변수를 hiding 해도 ::로 호출해서 사용 할 수 있다.

예제

#include <iostream>

using namespace std;

int value = 123;

int main()
{
	cout << value << endl;

	int value = 1;
	cout << ::value << endl;
	cout << value << endl;
	return 0;
}

123
123
1

  • 정적(static) 변수
    - static int a가 선언이 될 때 변수 a의 메모리 주소가 고정된다는 뜻이다.
    - 처음에 static 변수를 선언할 때 반드시 초기화를 해야한다.
    - 어떤 이유로 다시 같은 선언이 반복될 때 메모리 주소가 고정이 되어있기 때문에 새로 선언이나 초기화 되지 않고 넘어간다.
    - 주로 debug 할 때 사용

예제

#include <iostream>

using namespace std;

void doSomething()
{
	🔴int a = 1;
    	🔵static int a = 1;
	++a;
	cout << a << endl;
}

int main()
{
	doSomething();
	doSomething();
    	doSomething();
    	doSomething();
        doSomething();
        doSomething();

	return 0;
}

🔴 일 때
2
2
2
2

🔵 일 때
2
3
4
5

"디버깅 해보면 static int a 는 처음에만 초기화 된다."



다른 cpp파일의 함수 호출 방법 (include "경로" 말고)

예제

main.cpp

#include <iostream>

using namespace std;
// forward declaration
/*extern*/ void doSomething();
extern int a;

int main()
{
	doSomething();
	doSomething();

	cout << a << endl;

	return 0;
}

test.cpp

#include <iostream>

extern int a = 123;

void doSomething()
{
	using namespace std;
	cout << "hello " << endl;
}
  • 아무것도 없이 전방선언을 해두면 컴파일러는 다른 cpp파일에서 선언 했겠구나 하고 찾는다
  • 다른 cpp파일에서 전방선언한 (위에 예시를 든) 함수를 발견하면 linking 한다.
  • extern 은 생략가능

**

전역 변수 선언 시

Internal linkage

  • 다른 cpp 파일에서 접근하여 사용할 수 없는 전역 변수
    - static int g_x;
    - const int g_x(1);

external linkage

  • 다른 cpp 파일에서 접근하여 사용할 수 있다.
    - int g_x;
    - extern int g_x(1);

예제 1) : 상수를 전역 변수로 사용하여 전체 파일에서 사용하고 싶다.

main.cpp

#include <iostream>
#include "MyConstants.h"

void doSomething();

int main()
{
	using namespace std;

	cout << "In main.cpp file : \t" << Constants::pi << " " 
		<< &Constants::pi << endl;
	doSomething();

	return 0;
}
test.cpp

#include<iostream>
#include"MyConstants.h"

void doSomething()
{
	using namespace std;

	cout << "In test.app : \t\t" << Constants::pi << " " 
		<< &Constants::pi << endl;
}
MyConstants.h

#pragma once

namespace Constants
{
	const double pi(3.141592);
	const double gravity(9.8);
	// ...
}

In main.cpp file : 3.14159 00699B30
In test.app : 3.14159 00699B70

같은 전역 변수를 사용했는데 메모리 위치가 다르다.
=> 각자 따로따로 메모리를 사용한다.
=> 많이 사용하게 된다면 메모리를 엄청 많이 차지할 것 이다.
=> 헤더파일에서는 전역 상수 이름만 선언, cpp파일을 만들어서 상수 초기화, 초기화 한 변수를 사용하면 하나의 메모리로 모두 표현 가능하다.

MyConstants.h

#pragma once

namespace Constants
{
	extern const double pi;
	extern const double gravity;
	// ...
}
MyConstants.cpp

namespace Constants
{
	extern const double pi(3.141592);
	extern const double gravity(9.8);
}

In main.cpp file : 3.14159 00229B68
In test.app : 3.14159 00229B68

참조하는 메모리주소가 같음을 확인할 수 있다.



Auto 키워드와 자료형 추론

  • 자료형을 사용하여 선언하지 않고 auto 키워드를 이용하여 사용한다.
  • 편리하다.
  • 남발하면 나중에 알아보기 힘들수가 있다.
  • 가독성을 높이기 위해 -> 를 사용하기도 한다
auto add(int x, int y) -> int
{
	return x + (double)y;
}

int main()
{
	auto a = 123; // 형 추론
	auto d = 123.0;
	auto c = 1 + 2.0;
	auto result = add(1, 2);

	return 0;
}


형변환

  • 명시적 형변환, 암시적 형변환

암시적 형변환

  • numeric promotion : 작은 데이터형에서 큰 데이터형으로 암시적 형변환
    - float a = 1.0f; => double d = a;
  • numeric conversion : 타입이 바뀌거나, 큰 것을 작은거로 암시적 형변환 (문제발생 가능)
    - double d = 3;, short s = 2;

문제 발생 예제

int a = 30000;
char c = i;
// c는 문자형이라 숫자로 안나옴. 결과 값 확인을 위해 static casting 함
cout << static_cast<int>(c) << endl;

48

  • unsigned 경우
    - cout << 5u - 10 ; => 이상한 값 나옴

명시적 형변환

  • static_cast<int>(c)
  • int c = (int) 4
  • int c = int(4)

꿀팁 : 아래 코드는 데이터 타입을 리턴해준다

#include <typeinfo>
cout << typeid(variable or data).name() << endl;


문자열 std::string 소개

  • std::getline(std:cin, 변수)
  • string변수.length();


열거형

예제

#include <iostream>
#include <typeinfo>

enum Color // user-defined data types
{
	COLOR_BLACK,
	COLOR_RED,
	COLOR_BLUE,
	COLOR_GREEN,
	COLOR_ORANGE,
	// ...
};

enum Feeling
{
	HAPPY = -3 ,
	JOY,
	TIRED,
	BLUE,
};

int main()
{
	using namespace std;

	Color paint = COLOR_BLACK;
	Color house(COLOR_BLUE);
	Color appe{ COLOR_RED };

	Color my_color = COLOR_BLACK;
	Feeling my_feeling = TIRED;

	cout << my_color << " " << COLOR_RED << endl;
	cout << my_feeling << " " << HAPPY << endl;

	return 0;
}


영역 제한 열거형 (Enum Class)

  • 다른 Enum 끼리 비교할 때, 가르키는 정수가 같으면 서로 같은 것으로 인식한다.
  • Enum Class로 선언하면 해결 가능하다.

예제

enum class Color
{
	RED,
	BLUE,
};

enum class Fruit
{
	BANANA,
	APPLE,
};

int main()
{
	using namespace std;

	Color color = Color::RED;
	Fruit fruit = Fruit::BANANA;
    	// RED와 BANANA는 둘다 0 이지만 다른 것으로 인식 한다.
        return 0;
 }


구조체 (struct)

  • 다양한 요소를 포함하고 있는 것을 하나의 변수로 표현하긴 어렵다.
  • 사람을 변수로 생각한다면 한 사람당 키,몸무게,이름,나이 등등 요소가 많고, 사람을 여러명 선언한다고 가정하면 하나의 변수로 표현하기 어렵다.
  • 여러 요소를 하나의 자료형인거처럼 합쳐서 사용할 수 있게 해주는 것이 구조체다.

사용법 예제

#include <iostream>
#include <string>

using namespace std;

struct Person
{
	double	height;
	float	weight;
	int		age;
	string	name = "NONE";

	void print()
	{
		cout << height << " " << weight << " " << age << " " << name;
		cout << endl;
	}
};

Person getMe()
{
	Person me{ 2.0, 100.0, 20, "Jack" };

	return me;
}


int main()
{
	Person a;
	cout << a.name << endl;

	Person me{ 2.0, 100.0, 20, "Jack" };
	Person me2(me);
	Person me3;

	me3 = me;
	
	me.print();
	me2.print();
	me3.print();

	return 0;
}

NONE
2 100 20 Jack
2 100 20 Jack
2 100 20 Jack

예제 - Padding

struct Employee		// 2 + 4 + 8 = 14 
{
	short	id;		// 2 bytes
	int		age;	// 4 bytes
	double	wage;	// 8 bytes
};

int main()
{
	Employee emp1;
	cout << sizeof(Employee) << endl;

	return 0;
}

16

  • 구조체 크기는 short int double 하나씩 갖고 있으므로 14 byte여야 하는데 sizeof로 확인을 해보니 16이 나왔다.
  • 컴퓨터는 변수를 메모리에서 CPU 레지스터로 한번에 읽을 수 있도록 CPU 레지스터의 읽기 블록에 맞춰 정렬하는 컴파일러의 최적화 작업을 하게 된다.
  • 이를 패딩(padding)이라고 한다.
profile
https://github.com/velmash

0개의 댓글