728x90
반응형
오늘 오전 수업에서 c언어에서 쓰이는 몇가지 개념들에 대한 차이를 배웠습니다.
바이너리모드와 텍스트모드의 차이, 저수준 함수와 고수준 함수의 차이, 배열과 포인터의 차이입니다.
오후 수업에는 tcp/ip에서 통신규약으로 지정된 빅인디언을 사용하기 위해
빅인디언 리틀인디언의 컨버팅에 대해 배웠습니다.
1. 바이너리 모드와 텍스트 모드의 동작 방식
1) 파일을 읽을 때의 바이너리 모드와 텍스트 모드 : 파일을 읽을 때 데이터를 읽고 파일 커서가 이동하는 동작방식은 동일하다.
-----------------------------------------
FILE *fp;
char ch;
fp = fopen("a.txt", "w"); // 텍스트 모드로 열기 (fopen의 두번째 인자에서 "b"를 쓰지 않으면 텍스트 모드이다.)
혹은 fp = fopen("a.txt", "wb"); //이진 모드로 열기.
fscanf(fp, "%c", &ch);
-----------------------------------------
a.txt에는 61의 값이 있고 위와 같은 코드가 있을 때의 동작을 그림으로 나타내면 아래와 같다.
파일의 데이터(61)을 읽고나서 파일 커서가 이동한다.
이러한 동작은 바이너리모드와 텍스트 모드가 동일하다.
2) 바이너리 모드와 텍스트 모드의 차이 : 개행문자에 관해 약간의 차이가 있다.
파일에 데이터를 읽거나 쓸 때에는 해당 동작 후 파일 커서가 이동하는 것은 동일하다.
다만 개행을 처리하는 것에 차이가 있다.
텍스트 모드의 개행문자는 '\n'으로 처리되지만 바이너리 모드의 경우 '\r''\n'으로 처리한다.
그래서 문제가 발생할 수 있다. 텍스트 모드로 파일을 읽을 때에 '\r'이 생략되기 때문이다.
따라서 이런 문제를 해결하기 위해서는 이진모드로 파일을 열면 된다.
2. 저수준과 고수준의 차이
1) 파일 저장시 고수준과 저수준 함수의 차이 : 디스플레이 기반(고수준) / 메모리 기반(저수준)
파일에 데이터를 저장할때 쓰이는 고수준과 저수준 함수들은 데이터를 인식하는 기준에 차이가 있다.
고수준 함수는 화면에 출력되는 값을 아스키코드로 저장하는 반면
저수준 함수는 메모리에 저장되어 있는 실제 변수의 값을 저장한다.
아래의 코드는 fprintf() 함수로 데이터에 파일을 쓰는 코드이다.
-----------------------------------
FILE *fp;
int iNum = 0x12345678;
fp = fopen("A.txt", "w");
// 이때 운영체제가 파일을 여는데 파일의 정보가 있는 구조체를 만든다. fopen()는 그 구조체의 주소를 반환한다.
fprintf("fp, "%d", iNum); //fp를 통해 A.txt 파일에 iNum의 값인 0x12345678을 쓴다.
fclose(fp);
-----------------------------------
예상 결과는 A.txt 파일에 iNum의 크기인 4바이트만큼의 값이 쓰여져야 한다.
하지만 결과는 다르다.
A.txt에 9바이트 만큼의 값이 저장되어 있다.
그 값은 9개의 문자인 305419896의 아스키코드 값이다. (305419896은 0x12345678의 10진수 값이다.)
결국 fprintf()함수는 4바이트의 0x12345678의 실제 데이터 값을 저장하는 것이 아니라
각각을 하나의 문자로 간주하여 저장한다. 결국 고수준 함수 fprintf()함수는 보여지는 값인
디스플레이기반으로 데이터를 저장한다고 할 수 있다.
위의 소스에서 fprintf()가 아닌 write()를 쓸 경우의 결과를 살펴보자.
일단 fprintf()함수를 주석처리하고 아래와 같이 코드를 수정한다.
fwrite(&iNum, 1, 4, fp);
//여기서 두번째와 세번째 인수의 의미는 파일에 저장되는 데이터의 크기를 말한다.
//세번째 인수의 크기만큼 두번째 인수만큼 저장하라는 뜻으로
//4바이트를 1번 저장하라는 것이다.
결과는 아래와 같다.
정상적으로 4바이트만큼의 0x12345678이 저장된다.
write()함수는 실제 데이터값을 저장하는 것을 알 수 있다.
fprintf()와 write()함수를 비교해봄으로써 고수준 함수의 한계를 알 수 있으며
이런 부족한 점을 매꿔줄 수 있는 저수준 함수의 성능을 알아보았다.
저수준 함수가 세부적인 것 까지(예를 들면 위의 예에서는 저장될 데이터의 크기)를 정해줘야하는 귀찮음이 있지만
성능은 강력하다는 것을 알 수 있다.
3. 포인터와 배열의 비교
1) 배열과 포인터의 문자열이 메모리에 저장되는 방식 - 동일하다.
C언어에서 포인터와 배열의 표기법은 다르지만 내부적으로 메모리에 동작하는 방식은 동일하다.
char T[] = "ABCDE";
위와 같은 코드가 있을 때 메모리에는 65 66 67 68 69 00 이 저장된다.(각 값은 ABCDE의 아스키 코드값이며 00은 NULL이다.)
char *T = "ABCDE";
라는 코드가 있을 때 메모리에는 배열과 같은 65 66 67 68 69 00이 저장된다.
2) 배열과 포인터의 데이터 타입 차이 - 기본 자료형은 같으나 약간의 차이가 있다.
char T[] = "ABCDE";
char *p;
p=T;
위와 같은 코드가 있을 때 배열과 포인터의 심볼 테이블을 살펴보자. (번지는 임의로 설정했음)
----------------------
자료형 이름 번지
----------------------
char [] T 100
char * P 96
-------------------
배열과 포인터 자료형의 생김세는 다르다.
하지만 배열을 포인터 자료형으로 표현하면 char * const T 가 된다.
따라서 배열의 정확한 의미는 포인터 변수이되 포인터가 가르키는 주소값은 변하지 않는 상수라는 의미이다.
결국 p = T;라는 식이 성립할 수 있는 이유는
포인터와 배열의 기본적인 자료형이 포인터 변수이기 때문이다.
하지만 특이한 점은 T = p;가 성립되지 않는다.
왜냐하면 상수의 값은 대입연산자로 인해 변하지 않기 때문이다.
T의 값은 주소이지만 그 이전에 변하지 않는 값인 상수인데
상수에 값을 대입하는 대입연산자를 쓰는 것은 오류가 된다.
3) 배열과 포인터의 값 주소값 표현 - 형태는 다르지만 의미하는 바는 같다.
--------------------
char *p;
char ch='a';
p=&ch;
--------------------
위와 같은 소스가 있을 때 ch 의 값을 바꾸기 위해 아래의 두가지 표현을 모두 쓸 수 있다.
*p = 'z';
p[0] = 'z';
즉 포인터는 배열로 표현가능하다.
*p = 'z';
*(p+0) = 'z'
위의 코드는 같은 의미이다.
이것을 응용하면 포인터와 배열의 값과 주소를 표현하는 방법을 알 수 있다.
----------------
값 | 주소
----------------
p[1] | &p[1]
*(p+1) | (p+1)
----------------
지금까지 살펴본 것 과 같이 배열과 포인터는 표현방식은 다르지만 메모리에 저장되는 방식은 같다.
다만 표현의 방식과 배열의 주소값은 변하지 않는 상수인 반면 포인터의 주소값은 변한다는 점에서 차이가 있다.
4. TCP / IP의 리틀인디언과 빅인디언
이러한 수업을 배우게 된 배경 :
네트워크의 통신규약에서 네트워크 상에서의 데이터 저장방식으로 빅인디언을 채택하였다.
따라서 리틀인디언을 사용하는 cpu의 경우 문제가 발생할 수 있다.
이것을 해결하기 위한 몇가지 함수가 있다.
1) htons(), htonl(), ntohs(), ntohl()
가. htons()
- host to network short 의 약자로 호스트(pc를 뜻한다.)에서 네트워크로 데이터를 보낼 때
메모리에 있는 2바이트 short형 데이터를 빅인디언방식으로 변환하여 전송한다.
이때 short형 데이터는 port number를 뜻한다.
나. htonl()
- host to network long의 약자로 호스트에서 네트워크로 데이터를 보낼 때
메모리에 있는 4바이트 long형 데이터를 빅인디언 방식으로 변환하여 전송한다.
이때 long형 데이터는 ip 주소를 뜻한다.
다. ntohs()
- network to host short의 약자로 네트워크에서 호스트로 데이터를 보낼 때 쓰는 함수이다.
데이터의 타입은 short형이며 port number가 들어있다.
라. ntohl()
- network to host long의 약자로 네트워크에서 호스트로 데이터를 보낼 때 쓰는 함수이다.
데이터의 타입은 long형이며 ip주소가 들어있다.
이상입니다. 오늘 하루도 수고하셨습니다. ^^
바이너리모드와 텍스트모드의 차이, 저수준 함수와 고수준 함수의 차이, 배열과 포인터의 차이입니다.
오후 수업에는 tcp/ip에서 통신규약으로 지정된 빅인디언을 사용하기 위해
빅인디언 리틀인디언의 컨버팅에 대해 배웠습니다.
1. 바이너리 모드와 텍스트 모드의 동작 방식
1) 파일을 읽을 때의 바이너리 모드와 텍스트 모드 : 파일을 읽을 때 데이터를 읽고 파일 커서가 이동하는 동작방식은 동일하다.
-----------------------------------------
FILE *fp;
char ch;
fp = fopen("a.txt", "w"); // 텍스트 모드로 열기 (fopen의 두번째 인자에서 "b"를 쓰지 않으면 텍스트 모드이다.)
혹은 fp = fopen("a.txt", "wb"); //이진 모드로 열기.
fscanf(fp, "%c", &ch);
-----------------------------------------
a.txt에는 61의 값이 있고 위와 같은 코드가 있을 때의 동작을 그림으로 나타내면 아래와 같다.
파일의 데이터(61)을 읽고나서 파일 커서가 이동한다.
이러한 동작은 바이너리모드와 텍스트 모드가 동일하다.
2) 바이너리 모드와 텍스트 모드의 차이 : 개행문자에 관해 약간의 차이가 있다.
파일에 데이터를 읽거나 쓸 때에는 해당 동작 후 파일 커서가 이동하는 것은 동일하다.
다만 개행을 처리하는 것에 차이가 있다.
텍스트 모드의 개행문자는 '\n'으로 처리되지만 바이너리 모드의 경우 '\r''\n'으로 처리한다.
그래서 문제가 발생할 수 있다. 텍스트 모드로 파일을 읽을 때에 '\r'이 생략되기 때문이다.
따라서 이런 문제를 해결하기 위해서는 이진모드로 파일을 열면 된다.
2. 저수준과 고수준의 차이
1) 파일 저장시 고수준과 저수준 함수의 차이 : 디스플레이 기반(고수준) / 메모리 기반(저수준)
파일에 데이터를 저장할때 쓰이는 고수준과 저수준 함수들은 데이터를 인식하는 기준에 차이가 있다.
고수준 함수는 화면에 출력되는 값을 아스키코드로 저장하는 반면
저수준 함수는 메모리에 저장되어 있는 실제 변수의 값을 저장한다.
아래의 코드는 fprintf() 함수로 데이터에 파일을 쓰는 코드이다.
-----------------------------------
FILE *fp;
int iNum = 0x12345678;
fp = fopen("A.txt", "w");
// 이때 운영체제가 파일을 여는데 파일의 정보가 있는 구조체를 만든다. fopen()는 그 구조체의 주소를 반환한다.
fprintf("fp, "%d", iNum); //fp를 통해 A.txt 파일에 iNum의 값인 0x12345678을 쓴다.
fclose(fp);
-----------------------------------
예상 결과는 A.txt 파일에 iNum의 크기인 4바이트만큼의 값이 쓰여져야 한다.
하지만 결과는 다르다.
A.txt에 9바이트 만큼의 값이 저장되어 있다.
그 값은 9개의 문자인 305419896의 아스키코드 값이다. (305419896은 0x12345678의 10진수 값이다.)
결국 fprintf()함수는 4바이트의 0x12345678의 실제 데이터 값을 저장하는 것이 아니라
각각을 하나의 문자로 간주하여 저장한다. 결국 고수준 함수 fprintf()함수는 보여지는 값인
디스플레이기반으로 데이터를 저장한다고 할 수 있다.
위의 소스에서 fprintf()가 아닌 write()를 쓸 경우의 결과를 살펴보자.
일단 fprintf()함수를 주석처리하고 아래와 같이 코드를 수정한다.
fwrite(&iNum, 1, 4, fp);
//여기서 두번째와 세번째 인수의 의미는 파일에 저장되는 데이터의 크기를 말한다.
//세번째 인수의 크기만큼 두번째 인수만큼 저장하라는 뜻으로
//4바이트를 1번 저장하라는 것이다.
결과는 아래와 같다.
정상적으로 4바이트만큼의 0x12345678이 저장된다.
write()함수는 실제 데이터값을 저장하는 것을 알 수 있다.
fprintf()와 write()함수를 비교해봄으로써 고수준 함수의 한계를 알 수 있으며
이런 부족한 점을 매꿔줄 수 있는 저수준 함수의 성능을 알아보았다.
저수준 함수가 세부적인 것 까지(예를 들면 위의 예에서는 저장될 데이터의 크기)를 정해줘야하는 귀찮음이 있지만
성능은 강력하다는 것을 알 수 있다.
3. 포인터와 배열의 비교
1) 배열과 포인터의 문자열이 메모리에 저장되는 방식 - 동일하다.
C언어에서 포인터와 배열의 표기법은 다르지만 내부적으로 메모리에 동작하는 방식은 동일하다.
char T[] = "ABCDE";
위와 같은 코드가 있을 때 메모리에는 65 66 67 68 69 00 이 저장된다.(각 값은 ABCDE의 아스키 코드값이며 00은 NULL이다.)
char *T = "ABCDE";
라는 코드가 있을 때 메모리에는 배열과 같은 65 66 67 68 69 00이 저장된다.
2) 배열과 포인터의 데이터 타입 차이 - 기본 자료형은 같으나 약간의 차이가 있다.
char T[] = "ABCDE";
char *p;
p=T;
위와 같은 코드가 있을 때 배열과 포인터의 심볼 테이블을 살펴보자. (번지는 임의로 설정했음)
----------------------
자료형 이름 번지
----------------------
char [] T 100
char * P 96
-------------------
배열과 포인터 자료형의 생김세는 다르다.
하지만 배열을 포인터 자료형으로 표현하면 char * const T 가 된다.
따라서 배열의 정확한 의미는 포인터 변수이되 포인터가 가르키는 주소값은 변하지 않는 상수라는 의미이다.
결국 p = T;라는 식이 성립할 수 있는 이유는
포인터와 배열의 기본적인 자료형이 포인터 변수이기 때문이다.
하지만 특이한 점은 T = p;가 성립되지 않는다.
왜냐하면 상수의 값은 대입연산자로 인해 변하지 않기 때문이다.
T의 값은 주소이지만 그 이전에 변하지 않는 값인 상수인데
상수에 값을 대입하는 대입연산자를 쓰는 것은 오류가 된다.
3) 배열과 포인터의 값 주소값 표현 - 형태는 다르지만 의미하는 바는 같다.
--------------------
char *p;
char ch='a';
p=&ch;
--------------------
위와 같은 소스가 있을 때 ch 의 값을 바꾸기 위해 아래의 두가지 표현을 모두 쓸 수 있다.
*p = 'z';
p[0] = 'z';
즉 포인터는 배열로 표현가능하다.
*p = 'z';
*(p+0) = 'z'
위의 코드는 같은 의미이다.
이것을 응용하면 포인터와 배열의 값과 주소를 표현하는 방법을 알 수 있다.
----------------
값 | 주소
----------------
p[1] | &p[1]
*(p+1) | (p+1)
----------------
지금까지 살펴본 것 과 같이 배열과 포인터는 표현방식은 다르지만 메모리에 저장되는 방식은 같다.
다만 표현의 방식과 배열의 주소값은 변하지 않는 상수인 반면 포인터의 주소값은 변한다는 점에서 차이가 있다.
4. TCP / IP의 리틀인디언과 빅인디언
이러한 수업을 배우게 된 배경 :
네트워크의 통신규약에서 네트워크 상에서의 데이터 저장방식으로 빅인디언을 채택하였다.
따라서 리틀인디언을 사용하는 cpu의 경우 문제가 발생할 수 있다.
이것을 해결하기 위한 몇가지 함수가 있다.
1) htons(), htonl(), ntohs(), ntohl()
가. htons()
- host to network short 의 약자로 호스트(pc를 뜻한다.)에서 네트워크로 데이터를 보낼 때
메모리에 있는 2바이트 short형 데이터를 빅인디언방식으로 변환하여 전송한다.
이때 short형 데이터는 port number를 뜻한다.
나. htonl()
- host to network long의 약자로 호스트에서 네트워크로 데이터를 보낼 때
메모리에 있는 4바이트 long형 데이터를 빅인디언 방식으로 변환하여 전송한다.
이때 long형 데이터는 ip 주소를 뜻한다.
다. ntohs()
- network to host short의 약자로 네트워크에서 호스트로 데이터를 보낼 때 쓰는 함수이다.
데이터의 타입은 short형이며 port number가 들어있다.
라. ntohl()
- network to host long의 약자로 네트워크에서 호스트로 데이터를 보낼 때 쓰는 함수이다.
데이터의 타입은 long형이며 ip주소가 들어있다.
이상입니다. 오늘 하루도 수고하셨습니다. ^^
728x90
'코스웨어 > 11년 내장형하드웨어' 카테고리의 다른 글
[내장형]윤민석 2011년 7월 6일 수업내용 (21) | 2011.07.06 |
---|---|
[내장형]김동화 2011년7월 5일 수업내용 (14) | 2011.07.05 |
[내장형]이성재 2011년7월4일 수업내용 (15) | 2011.07.04 |
[내장형]최남식-2011년7월1일 수업내용 (11) | 2011.07.02 |
[내장형]김수만_2011년6월29일_수업내용 (22) | 2011.06.30 |
[내장형]김수만_포스트에 C Code를 웹브라우저에서 보기 좋게 삽입하기 (6) | 2011.06.28 |
[내장형]최남식-가입인사 (0) | 2011.06.28 |
[내장형]최성태_20110628 수업내용 (24) | 2011.06.28 |