출처 : 잡동사니님 블로그


- 1Bytes 변수( char, unsigned char 등 )를 제외한 변수를 초기화 할 때는 0 이외의 값으로 초기화를 하면 안됨

- new, malloc 등을 이용하여 동적으로 배열을 생성하는 변수가 있는 struct, class에서는 memset으로 초기화를 하면 안됨

- CString은 절대 memset으로 초기화를 하면 안됨

- virtual function을 가지고 있는 struct, class에서는 절대 memset으로 초기화를 하면 안됨


memset을 사용할 때 위 4가지 경우만 기억을 하고 있으면 문제없이 동작합니다. 

각각에 대해서 간단하게 살펴보도록 하죠


-1Bytes 변수( char, unsigned char 등 )를 제외한 변수를 초기화 할 때는 0 이외의 값으로 초기화를 하면 안됩니다.

1
2
int n;
memset(&n, 1, sizeof(int));

으로 하면 Byte단위로 처리가 되어 

n = [00000001000000010000000100000001] = 16843009의 원하지 않는 값으로 초기화가 되버립니다. 

따라서 1Byte의 변수를 제외하고는 0으로만 초기화를 하는데 이용해야 합니다.


-new, malloc 등을 이용하여 동적으로 배열을 생성하는 변수가 있는 struct, class에서는 memset으로 초기화를 하면 안됩니다

문제가 되는 경우를 살펴보면,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct A
{
   int i;
   char* c;
};
  
void main()
{
   A a;
   a.c = new char[100];
   memset(&a, 0, sizeof(A));
   if(a.c != NULL)
   {
      delete[] a.c;
      a.c = NULL;
   }
}

여기서 sizeof(A)는 struct member alignment가 어떤 값이든 4(int i) + 4(char* c, address는 4) = 8Bytes가 됩니다. 

그러므로 위의 소스는 동적으로 생성한 변수는 초기화가 되지 못하고, char* c가 NULL로 초기화가 됨으로써, 

이전에 생성한 메모리는 메모리 누수가 발생하게 됩니다.

그러므로 위와 같이 동적으로 생성하는 경우는 아래와 같이 각각을 분리하여 초기화를 하여야 합니다.

1
2
a.i = 0;
memset(a.c, 0, sizeof(char)*100);


-CString은 절대 memset으로 초기화를 하면 안됩니다.

1.2와 같은 경우로 CString은 내부적으로 m_pchData 변수를 동적으로 생성하여 문자열을 저장합니다. 

이 변수에 대한 직접적인 접근은 private로 막혀 있습니다.

그래서 CString, 또는 CString을 member variable을 가지고 있는 

struct, class를 memset을 이용하여 초기화를 하면 안됩니다.

CString을 memset으로 초기화를 하면, 1.2와 같이 메모리 누수뿐만 아니라, run-time error도 발생을 합니다.


-virtual function을 가지고 있는 struct, class에서는 절대 memset으로 초기화를 하면 안됩니다.

여기서 virtual은 run-time에 실행함수를 binding하는 역할을 하는 것입니다.

한번 잊어버렸던 기억을 되살리는 의미로 예제를 살펴보면,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
{
public:
   void fun() { printf("A::fun() "); }
};
  
class B: public A
{
public:
   void fun() { printf("B::fun() "); }
};
  
void main()
{
   A* a = new B();
   a->fun();
}

위의 경우 “A::fun()”이 출력됩니다.

하지만 상속을 하여 재정의를 한다는 목적은 재정의를 한 함수가 호출되기를 바라기 때문이죠.

이때 아래와 같이 class A만 간단히 변경하여 virtual만 추가를 하면,

1
2
3
4
5
class A
{
public:
   virtual void fun() { printf("A::fun() "); }
};

재정의한 함수가 실행이 되어 “B::fun()”이 출력됩니다. 이는 a→fun();가 실행이 될 때,

이 함수가 virtual이므로 a의 실제 instance(=new B)에 대응하는 실제 함수를 run-time으로 binding 되기 때문입니다.

이정도로만 virtual 동작에 대해서 기억을 되살려보는 것으로 마무리를 하고, 다시 memset으로 넘어오면,

1
2
3
4
5
6
class A
{
   int i;
   char* c;
   void fun();
};

을 sizeof(A)를 하면 4(int i)+4(char*c, address)=8Bytes로 member function은 영향을 주지 않습니다. 

하지만,

1
2
3
4
5
6
class A
{
   int i;
   char* c;
   virtual void fun();
};

의 경우는 다릅니다. 

위의 8Bytes외에 실제 fun()이 binding을 위한 

실행함수 주소를 저장할 공간을 가리키는(VPTR) 4Bytes를 추가적으로 가지므로, 

sizeof(A)는 총 12Bytes가 됩니다.

이때

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
{
public:
   virtual void fun() { printf("A::fun() "); }
};
  
class B: public A
{
public:
   void fun() { printf("B::fun() "); }
};
  
void main()
{
   A* a = new B();
   memset(a, 0, sizeof(B));
   a->fun();
}

와 같이 memset을 이용하여 초기화를 하면, virtual function이 NULL영역으로 binding이 되어

a→fun();에서 run-time에 알 수 없는 에러가 발생한다는 것을 반드시 기억해야 합니다.

memset은 매우 편리하고, 강력하면서도, 조심해서 사용해야 한다는 것을 명심하세요.



※요약

조회하려는 칼럼의 중복되는 값은 제거 후 보여준다.

DISTINCT 키워드 뒤에 2개 이상의 칼럼을 정의하면 

하나의 RECORD로 인식하여 DISTINCT 키워드 이후에 오는 칼럼에 대해 모두 중복 제거한다.



※예제

SELECT DISTINCT mgr FROM emp;

SELECT DISTINCT job, mgr FROM emp;



※예제에 쓰일 emp 테이블



※결과

SELECT DISTINCT mgr FROM emp



SELECT DISTINCT job, mgr FROM emp

'DB 및 SQL > SELECT문' 카테고리의 다른 글

[Oracle SQL] Alias - 컬럼에 별칭 붙이기  (2) 2013.11.30
[Oracle SQL] ORDER BY절 - DESC, ASC  (2) 2013.11.27
[Oracle SQL] SELECT문  (0) 2013.11.27



※요약

SELECT : 테이블 내의 데이터를 조회할 때 사용한다.



※예제

SELECT * FROM emp;



※설명

SELECT : 데이터를 조회하기 위해 사용되며, DQL(Data Query Language)이라고도 한다.

* : 테이블에 정의된 모든 필드(컬럼)를 조회한다.

FROM emp : 선택한 테이블명



※결과

'DB 및 SQL > SELECT문' 카테고리의 다른 글

[Oracle SQL] Alias - 컬럼에 별칭 붙이기  (2) 2013.11.30
[Oracle SQL] ORDER BY절 - DESC, ASC  (2) 2013.11.27
[Oracle SQL] DISTINCT 키워드  (0) 2013.11.27

※요약

fputs : 개방된 파일에 문자열을 라인 단위로 씁니다.



※특징

개행 문자 '\n'을 자동으로 0x0D, 0x0A 값으로 변환한다.



※함수 원형 및 설명

int fputs( const char *string, FILE *stream );
//string : 파일에 쓸 NULL로 끝나는 문자열 버퍼의 포인터
//stream : 개방된 FILE 구조체의 포인터
//반환값 : 설공 시 0이나 양수, 실패 시 EOF(-1)




※예제

#include <stdio.h>

int main( )
{	
	FILE *pFile = NULL;

	pFile = fopen( "d:\\Text.txt", "w+" );
	if( pFile != NULL )
	{
		for( int i=0 ; i<5 ; ++i )
		{
			int nResult = fputs( "라인 단위 파일 쓰기 fputs\n", pFile );
			printf( "%d번째 라인 쓰기 %s\n", i+1, nResult != -1 ? "성공":"실패" );
		}
		fclose( pFile );
	}
	else
	{
	}

	return 0;
}




※요약

fgets : 개방된 파일에서 텍스트 문자열을 한 줄씩 읽습니다.



※특징

 - 파일 끝이나 개행 문자까지 읽는다.

 - 라인 끝(CR/LF)을 읽으면 개행 문자 '\n'으로 변환한다.

 - string 끝에 NULL문자를 추가한다.



※함수 원형 및 설명

char *fgets( char *string, int n, FILE *stream );
//string : 파일 데이터를 읽어서 저장할 버퍼의 포인터
//n : 읽을 최대 문자의 수 +1, 읽은 문자열의 끝에 NULL이 추가
//stream : 개방된 FILE 구조체의 포인터
//반환값 : 읽은 string의 포인터, 더 읽을 파일이 없거나 에러 시 NULL 포인터



※예제

#include <stdio.h>

int main( )
{
	FILE *pFile = NULL;

	pFile = fopen( "d:\\Text.txt", "r" );
	if( pFile != NULL )
	{
		char strTemp[255];
		char *pStr;

		while( !feof( pFile ) )
		{
			pStr = fgets( strTemp, sizeof(strTemp), pFile );
			printf( "%s", strTemp );
			printf( "%s", pStr );
		}
		fclose( pFile );
	}
	else
	{
		//에러 처리
	}

	return 0;
}


※txt파일 내용

첫 번째줄입니다.

두 번째줄입니다.

세 번째줄입니다.




※요약

fopen : 파일에 대한 입력 및 출력을 합니다.

fclose : fopen함수로 개방한 파일을 닫습니다.


※함수 원형 및 설명

FILE *fopen( const char *filename, const char *mode );
//filename : 개방할 파일의 경로 및 파일명
//mode : 파일 접근 권한(읽기 전용, 쓰기 전용 등 아래 표 참고)
//반환값 : 개방된 파일의 FILE 구조체 포인터, 실패시 NULL포인터

int fclose( FILE *stream );
//stream : 개방된 FILE 구조체의 포인터
//반환값 : 성공 시 0, 실패 시 -1(EOF)



※모드 설명

 모드

 설명

읽기만 가능하며 파일이 존재해야 한다.

존재하지 않을 경우 에러가 리턴된다.

 w

쓰기만 가능하며 파일을 생성한다.

파일이 존재하면 그 파일을 지우고 생성한다.

 a

파일 끝에 추가만 가능하며 

파일이 존재하지 않으면 파일을 새로 생성한다. 

 r+

읽기, 쓰기 모두 가능하며 파일이 존재해야 한다. 

존재하지 않을 경우 에러가 리턴된다.

 w+

 읽기, 쓰기 모두 가능하며 파일을 생성한다.

파일이 존재하면 그 파일을 지우고 생성한다.

 a+

파일을 읽어서 파일 끝에 추가만 가능하다.

파일이 존재하지 않으면 파일을 새로 생성한다. 

 t

 파일을 text 모드로 개방한다. 

입력 시, CF/LF를 “\n”으로 자동 변환하고 

출력 시에는 “\n”을 CF/LF로 자동 변환한다.

t나 b 생략시 텍스트 모드로 개방된다.

 b

 파일을 이진(binary) 모드로 개방한다.

개행 문자 “\n”을 변환없이 그대로 읽고 쓴다.

파일 개방 시 기본 모드는 텍스트 모드인 t모드입니다.

고로 r은 rt와 같고 r+는 r+t와 같습니다.



※모드 조합

 모드

읽기

쓰기

추가

 텍스트 모드

r / rt

w / wt

a / at

 텍스트 갱신 모드

r+ / r+t

w+ / w+t

a+ / a+t

 이진 모드

rb

wb

ab

 이진 갱신 모드

r+b

w+b

a+b



※모드표

모드

읽기

쓰기

갱신

파일 없을 시

파일 생성

파일 존재 시

삭제 여부

fseek함수

사용 여부

r

O

X

X

X

X

O

r+

O

O

O

X

X

O

w

X

O

O

O

O

O

w+

O

O

O

O

O

O

a

X

O(*)

X

O

X

X(*)

a+

O

O(*)

X

O

X

O

모드 a, a+는 현재의 FILE 포인터 위치에 관계없이 항상 파일 끝에 씁니다.

그러므로 fseek함수로 FILE 포인터 위치를 바꿔도 소용이 없으며, a+모드일 때 읽을 위치만을 설정합니다.

기존 파일을 삭제하지 않고 수정하려면 r+모드로 하면 됩니다.



※예제

#include <stdio.h>

int main( )
{
	FILE *pFile = NULL;

	pFile = fopen( "d:\\text.txt", "w+t" );
	if( pFile != NULL )
	{
		fputs( "테스트 입니다.", pFile );
		fclose( pFile );
	}
	else
	{
		//에러 처리
	}

	return 0;
}




버추얼박스 포터블 만들기 입니다.


먼저 아래의 주소들에서 파일 2개를 다운 받습니다.

http://www.vbox.me/

https://www.virtualbox.org


파일을 다운 받습니다.


다운 받은 파일 2개를 보기 편하게 하나의 폴더에 모아둡니다.


먼저 "Portable-VirtualBox*" 파일을 실행해서 파일을 추출하면 "Portable-VirtualBox"라는 폴더가 생깁니다.


폴더에 들어가서 "Portable-VirtualBox.exe"파일을 실행합니다.


그럼 아래와 같이 프로그램이 실행되는데,

"seach"버튼을 눌러 처음에 다운 받은 "VirtualBox-4.3.2-90405-Win"을 선택합니다.

그리고 원하는 Bit를 선택한 후 "OK" 버튼을 눌러 진행합니다.


진행이 완료되고 "Portable-VirtualBox.exe"를 실행하면 아래와 같이 VirtualBox가 실행됩니다.




흔히 인터넷 광고를 볼 때 아래와 같이 100Mbps라는 문구를 자주 보셨을 겁니다.


위와 같이 광고 했을 때 흔히 다운로드 속도가 100MB/s가 나올거 같은데

실제로는 최대 12.5MB/s가 최고 속도입니다.

그럼에도 불구하고 100Mbps라고 표기하고 광고하는 건 

10이라는 숫자 보다는 100이라는 숫자가 더 크게, 더 빠르게 다가오기 때문입니다.


Mbps는 [Mega bit per second]의 약자로써, 우리가 흔히 사용하는 MB[Mega Byte]로 변환하려면

Mbps * 0.125 = MB/s와 같이 됩니다.

Mbps에 0.125를 곱해주는 이유는 1bit * 8 = 1Byte, 즉 1Byte는 8bit이기 때문입니다.(약자 bit와 Byte)

고로 Mbps * 0.125 = MB/s 대신 Mbps / 8 = MB/s도 되는 거구요.


상기와 같기 때문에 100Mbps는 100 * 0.125 = 12.5MB/s가 나오는 겁니다.

하지만 다운로드 받을때 아무리 해도 12.5MB/s가 나올 수가 없는게,

다운로드 받을때는 데이터만 받는게 아니라 헤더 등의 정보도 받기 때문에 보통 11MB/s정도의 속도가 나옵니다.


요즘 나오는 wi-fi 속도인 150Mbps와 300Mbps는 MB/s로 변환할 경우의 속도는 아래와 같습니다.

150Mbps == 18.75MB/s

300Mbps == 37.5MB/s


하지만 무선 인터넷 속도가 300Mbps라고 해서 상기와 같이 37.5MB/s가 나오지는 않습니다.

37.5MB/s는 커녕 100Mbps와 같은 12.5MB/s와 비슷한 속도가 나옵니다.

이는 대부분의 광랜 서비스 속도가 100Mbps라 그런겁니다.

굳이 비유하자면.. 내 차는 최대 430km/h를 달릴 수 있는 부가티 베이론인데

고속도로를 같이 달리는 모든 차들의 최대 속도는 150km/h이면 

430km/h의 속도를 못 내고, 같이 150km/h의 속도를 내야하는 것과 비슷합니다.


대신 내부망이 300Mbps 이상인 기가비트로 구성되어 있다면

내부 전송속도는 300Mbps 다 사용할 수 있습니다.


아래와 똑같이 체크해주고 내용을 적어주되, "보내는 사람" 항목은 마음대로 하고 싶은 걸로 하고 "사용자 이름"과 "암호" 항목에는 gmail의 아이디와 비밀번호를 넣어줍니다.


잘 되었는지 확인할겸 테스트 메일을 보내봅니다.

전자 메일 주소 1과 2는 각각 알림 받을 메일 주소를 적어줍니다.


전송 완료 후 바로 메일이 온 걸 확인할 수 있습니다.




※요약

isspace : 문자가 공백이나 개행, 탭인지 조사하는 함수



※함수 원형 및 설명

int isspace( int c );
//c : 검사할 문자 또는 아스키 값
//반환값 : 문자가 공백이나 개행, 탭 문자이면 true, 아니면 false


※예제

#include <stdio.h>
#include <ctype.h>

int main( )
{
	bool bCheck = false;
	char strTemp[] = " \n\t5";

	bCheck = isspace( strTemp[0] );
	printf( "%s\n", bCheck ? "True" : "False" );

	bCheck = isspace( strTemp[1] );
	printf( "%s\n", bCheck ? "True" : "False" );

	bCheck = isspace( strTemp[2] );
	printf( "%s\n", bCheck ? "True" : "False" );

	bCheck = isspace( strTemp[3] );
	printf( "%s\n", bCheck ? "True" : "False" );

	bCheck = isspace( '\n' );
	printf( "%s\n", bCheck ? "True" : "False" );

	return 0;
}


+ Recent posts