'공부합시다/C언어'에 해당되는 글 6건

  1. 2009.08.17 strtok()를 이용한 문자열 단어 교체 프로그램
  2. 2009.05.06 [C언어] 부호 확장(Sign extension)
  3. 2009.04.30 [C언어] 구조체의 메모리 저장방식과 #pragma pack
  4. 2009.04.20 [C언어]좀 더 복잡한 함수 포인터
  5. 2009.04.16 [C언어]Little Endian
  6. 2009.04.16 [C언어]함수 주소를 직접 입력하여 호출하기
2009. 8. 17. 17:17

strtok()를 이용한 문자열 단어 교체 프로그램

문자열은 30자로 제한

교체할 문자는 10자로 제한한다고 가정




실행화면


2009. 5. 6. 15:53

[C언어] 부호 확장(Sign extension)



결과는 다음과 같다.



int형 b에 같은 -1을 대입했는데 왜 결과 값은 다르게 나올까.

그 이유는 부호 확장에 있다.

int b = a 에서 a는 char 형이기 때문에, 묵시적인 형변환이 발생하게 되는데 이때, char형 데이터인 a를 바로 int형 데이터 b에 넣는 것이 아니라 a를 4바이트 크기로 확장을 하게 된다.

1바이트에서 4바이트로 확장을 하면서 나머지 빈 공간에는 음수면 1로 채우고 양수면 0으로 채우게 된다.

따라서 (signed) char 인 a변수는 앞에 1을 채워서 FFFFFFFF가 되고, unsigned char 인 c변수는 앞에 0을 채워서 FF가 되는 것이다.
2009. 4. 30. 17:25

[C언어] 구조체의 메모리 저장방식과 #pragma pack

구조체는 메모리에 어떤 식으로 저장될까
다음과 같은 소스를 보자.


TEST 구조체 변수인 TData는 char형 데이터(1byte), short형 데이터(2byte), int형 데이터(4byte)를 가지고 있으므로 1+2+4=7byte의 크기를 가질 것 처럼 보인다. 하지만 이 소스를 컴파일하고 실행을 해보면 다음과 같은 결과가  나온다.



분명히 cData(1) + sData(2) + iData(4) = 7임에도 불고하고 TData의 크기는 8바이트라고 하니 참 이상한 일이다.

이는 현재 우리가 쓰는 32비트 컴퓨터에서 32비트 컴파일러를 사용하였기 때문에 32비트 즉, 4바이트로 데이터를 처리하는 것에 가장 최적화되어 있기 때문에 데이터를 4바이트 공간으로 저장하기 때문이다.

이 TData란 구조체는 8바이트에 다음과 같이 저장되어 있다.

cData
??
sData
sData
iData
iData
iData
iData

cData를 저장하고, 4바이트중에 3바이트가 남아있기 때문에 sData를 3바이트 중에 2바이트의 공간에 저장하고,
iData를 저장하려 하니 1바이트밖에 남아있지 않기 때문에 4바이트의 공간을 따로 만들어 저장하게 되는 것이다.

그럼 이제 위의 소스에서 변수 선언의 순서를 한 번 바꿔 보자.



변수 선언의 순서를 바꿨을 뿐인데 신기하게도 같은 구조체의 크기가 8에서 12로 늘어나버렸다.
이 TData 구조체 변수는 다음과 같이 저장되어 있을 것이다.

cData(1byte)
empty(3byte)
sData(2byte)
empty(2byte)
iData(4byte)

이처럼 컴파일러는 4바이트에 맞춰서 데이터를 저장하는 것을 볼 수 있다. 이것을 막으려면 어떻게 해야할까.

이것을 해결하려면 #pragma pack() 이라는 전처리어를 사용하면 된다.
구조체 하나를 더 추가한 다음 소스를 보자.



#pragma pack(1)에서 1은 1바이트 단위로 저장하겠다는 것이다. 따라서 TData와 TData2의 내용물은 같으나 크기는 다른 것을 확인할 수 있다.

 그렇다면, 왜 모두 1바이트로 해서 메모리의 낭비가 없도록 하지 않는 것일까?
 그것은, 아까도 이야기하였듯이 32비트 CPU에서는 4바이트(32비트)의 단위로 데이터를 처리하는 것이 가장 빠르게 때문이다. 즉, #pragma pack(1) 이라고 선언해놓고 원래대로 돌려놓지 않는다면 속도저하의 문제가 생길 수 있다.
 따라서, 위의 소스에서 구조체 선언이 끝나는 부분에 #pragma pack(4)라고 선언해주어 할 것이다.

 하지만, 여기에도 문제가 있다.
 만약, 이 소스를 32비트의 PC가 아닌 다른 CPU가 장착된 장비에서 컴파일하게 된다면 어떻게 될 것인가. 예를 들면 임베디드 시스템 같은 8~16비트 CPU에서 말이다.
 소스를 일일히 찾아서 CPU에 맞게 고쳐주고 다시 컴파일해야 되는 불편함과 어려움이 생기게 된다.

 이럴때를 위해서 좀 더 우아하게 쓰는 코드가 있다.



 기존의 바이트를 스택에 push하고 1바이트 단위로 처리한다음 끝나는 부분에 원래의 바이트 단위를 pop해주는 코드이다. 보통은 이렇게 사용하면 되겠다.

 pragma에는 다른 용도(warning을 표시하지 않게 한다던가하는 기능들)도 있지만, 이는 다음에 알아보도록 하자.
2009. 4. 20. 10:40

[C언어]좀 더 복잡한 함수 포인터


2009. 4. 16. 11:43

[C언어]Little Endian

Intel Cpu는 Little Endian 방식으로 데이터를 저장한다.



소스코드 에서 iNum 에 실제로 저장된 데이터

78

56

34

12

Little                                                                                  Big
End                                                                                 Start

little endian의 장점 산술연산
big endian의 장점 대수비교
2009. 4. 16. 11:15

[C언어]함수 주소를 직접 입력하여 호출하기

소스코드