C++, 4.변수의 범위와 더 다양한 변수형

이도현·2023년 8월 9일
0

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

  • 블록(복합분), 명칭 공간, 이름 충돌, 이름 숨김
  • {} 중괄호(블록)안에서 정의된 것은 벗어나면 사라진다.
  • 바깥에 선언된 것은 안에 들어갈 수 있지만 안에서 선언된 것은 바깥으로 나갈 수 없다.
  • 바깥에서 선언 된 것과 중괄호 안에 선언된 것의 이름이 같을 경우 바깥에서 선언된 이름은 숨겨진다.(이름 숨김)
  • 같은 이름이 충돌나면 그 코드는 사용할 수 없다.(이름 충돌)
  • 이름 충돌을 막기위해 명칭공간을 구분할수 있다. (namespace name {}, name::...)

2. 전역변수(Global variable), 정적변수(Static variable),

  • 내부연결(Internal Linkage), 외부연결(External Linkage)

전역 변수: 함수의 외부에서 선언된 변수
정적 변수: 프로그램이 종료되기 전까지 메모리가 소멸되지 않는 변수이다.

  • 함수를 벗어나도 변수가 사라지지 않고 유지된다.
  • 초기화 할 때 반드시 상수로 초기화해야한다.
  • 초깃값을 지정하지 않으면 디폴트값 0으로 자동 초기화 된다.
  • 내부연결: 파일 안에서 변수를 어디서든 사용할 수 있으면 내부연결

  • 외부연결: 한 cpp파일에서 정의한 변수를 다른 cpp파일에서 사용할 수 있는 것(정적 변수를 선언할 경우 외부연결안된다.)

//MyConstants.h

namespace Contants
{
      const double pi(3.141592);
      const double gravity(6.9);
}
// main.cpp

#include "MyConstants.h"
int main()
{
    cout << Constants::pi << endl;
}

main.cpp 에서 사용된 pi는 extern 붙이지 않고 가져왔기 때문에 쓰레기 값을 가진 pi이다 그러므로 메모리낭비일 뿐이다.

이를 막기위해 extern을 붙이는 것을 권장한다.

namespace Constants
{
    extern const double pi(3.131592);
    extern const double gravity(9.9);
}

3. Using문과 모호성

#include <iostream>  

using namespace std;

namespace a{
	int my_var(10);
}

namespace b{
	int my_var(20);
}

int main(){
	using namespace a;
	using namespace b;

	cout << my_var << endl; // 같은 변수명을 가진 것이 존재함으로 ambigious오류가 난다.
	                        // a::my_var, b::my_var
	                        // {}로 구역을 나누어 using namespace로 지역 변수를 나누어 사용하면 모호성 오류를 사전 
                            // 예방할 수 있다.
	return 0;
}

4. auto 키워드와 자료형 추론

#include <iostream>  

using namespace std;

auto add(int x, int y)
{
	return x + y;
}
int main()
{
	auto a = 123; // 초기화 type에 맞추어 자동으로 type을 정한다.
	auto c = 1 + 13.0;
	add(1, 2);

	return 0;
}

찍어보고 변수명에 마우스 갔다 대고 변수 type 확인하기 신기함.

5. 암시적 형변환Implicit Type Conversion(coersion)과

  • 명시적 현변환Explicit Type Conversion(casting)

암시적 형변환은 작은 범위의 자료형에서 넓은 범위의 자료형으로 변환할 때 일어난다.(반대의 경우 오류가난다.)

명시적 형변환은 넓은 범위의 자료형에서 작은 범위의 자료형으로 변환할 때 (변환할 타입)변수의 형태로 할당해 주어 명시하는 것이다.

ex) long a = 1;

   int b = (int)a;
#include <iostream>  
#include <typeinfo>

using namespace std;

int main()
{
	float a = 1.0f;
	double d = a; //numeric promotion

	//numeric conversion 형변환시 형식이나 크기에 맞게 변환하도록 유의한다.
	int i = 30000;
	char c = i;// char의 크기는 -255 ~ 255의 크기를 가지기 때문에 오류가 생긴다.

	cout << typeid(a).name() << endl;

	return 0;
}

6. 문자열 std string 소개

#include <iostream>  

using namespace std;

int main()
{
	const char my_strs[] = "Hello, World";
	const string my_hello = "Hello, World"; //일종의 사용자정의함수기 때문 char과 string
	                                        //색깔이 다르다

	cout << my_hello << endl;

	string a("Hello, ");
	string b("World");
	string hw = a + b; // append

	hw += "I'm good";

	cout << hw << endl;

	return 0;
}

찍어보자 재밌따.

7. 열거형 enumerated types

#include <iostream>  
#include <typeinfo>

using namespace std;

enum Color // user-defined data types
{
	COLOR_BLACK,
	COLOR_RED = 1, //이런식으로 선언 가능 여기서 1로 선언 했다면 다른 변수에는 1을 피해야한다.
	COLOR_BLUE,
	COLOR_GREEN,
	BLUE//블루가 같으니 피하는게 좋다.
};

enum Feeling
{
	HAPPY,
	JOY,
	TIRED,
	BLUE
};

int main()
{
	Color paint = COLOR_BLACK;
	Color house(COLOR_BLUE);
	Color apple(COLOR_RED);

	cout << paint << " " << apple << endl;

	return 0;

맛있다.

8. 영역 제한 열거형Scoped Enumerations(Enum Class)

#include <iostream>  
#include <typeinfo>

using namespace std;

int main()
{
	enum Color // 밑에 if 문에서 같다고 나오는 것은 의도와 다를 것이다. 
			   // enum 뒤에 class를 븉여 의도와 같게 움직이도록 할 수 있다. 찍어보자.
	{
		RED,
		BLUE,
	};

	enum Fruit
	{
		BANANA,
		APPLE,
	};

	Color color = RED;
	Fruit fruit = BANANA;

	if (color == fruit)
		cout << "Color is fruit ? " << endl;

	return 0;
}

9. 자료형에게 가명 붙여주기

#include <iostream>  
#include <vector>

using namespace std;

int main()
{
	typedef double distance_t; //메모겸 주석겸 가명을 붙여주었다. 
	                           //가명을 만들어서 사용할 경우 나중 단체로 type 변환시 편리

	typedef vector<pair<string, int> > pairlist_t;// 이런식으로 가명을 지어주면 편리

	using pairlist_t = vector<pair<string, int> >; // 위와 같은 결과를 도출시킨다.

	return 0;
}

가명을 지어줌으로써 편리하게 사용할 코드가 많아질 것 같다. 잘 활용해보자.

10. 구조체

  • 구조체란 하나 이상의 변수를 묶어서 새로운 자료형을 정의하는 도구이며 객체지향언어의 시발점
#include <iostream>  
#include <vector>

using namespace std;

struct Person
{
	double height; //height = 3.0이라고적어 defalt 값을 정해 놓을 수 있다.
	float weight;
	int age;
	string name;

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

//void printPerson(Person ps)
//{
//	cout << ps.height << " " << ps.weight << " " << ps.age << " " << ps.name;
//	cout << endl;
//} // 이것도 비효율적 

Person getMe()//구조체를 함수로 사용할 수 있다는 걸 보여주는 것
{
	Person me{ 2.0, 100, 20, "Jack Jack" };

	return me;
}

int main()
{
	Person me{2.0, 100, 20, "Jack Jack"};
	/*me.age = 20;
	me.name = "Jack Jack";
	me.height = 2.0;
	me.weight = 100.0;*/ //구조체를 사용하는 의미가 없다 위 처럼 uniform initialize 사용
	
	//printPerson(me);
	
	me.print();

	Person me_from_func = getMe();
	me_from_func.print();

	return 0;
}

찍어보고 어떤 과정으로 디버깅 되었는지 세세히 말로 설명해보자.

번외로
구조체 생성 후
cout << sizeof(stuct);
해봐서 공간을 여유롭게 만드는 구조체의 영특함을 맛봐보자.

profile
좋은 지식 나누어요

0개의 댓글