2007/07/31

A Book On C Chapter 6 연습문제 8번.

다음 프로그램은 어떤 값을 출력하는가? 설명하여라.

#include
typedef unsigned long ulong;

int main(void)
{
char *pc = NULL;
int *pi = NULL;
double *pd = NULL;
long double *pld = NULL;

printf("%5lu%5lu\n%5lu%5lu\n%5lu%5lu\n",
(ulong)(pc+1), (ulong)(pi+1),
(ulong)(pd+1), (ulong)(pld+1),
(ulong)(pc+3), (ulong)(pld+3));

return 0;
}

NULL은 0번지를 포인터하므로 pc, pi, pd, pld는 초기화 후에 0 값을 가진다.
pc+1 : pc는 char형 포인터이므로 1바이트 증가
pi+1 : pi는 int형 포인터이므로 4바이트 증가
pd+1 : pd는 double형 포인터이므로 8바이트 증가
pld+1 : long double형은 12바이트인거 같다.
pc+3 : 3바이트 증가
pld+3 : 36바이트 증가

2007/07/26

Process문

하드웨어 시스템의 모듈들은 서로간에 병행적으로 수행되므로 시스템의 동작으로 표현하기 위해서는 일반적으로 concurrent문을 사용하는 것이 바람직하다. 그리고 그 내부의 동작은 순차적으로 이루어진다고 볼 수 있으므로 sequential문을 사용하는 것이 좋다. Process문 자체는 concurrent문이므로 여러개의 process문이 있으면 이들은 병행적으로 수행되며, process문 내부는 하나씩 차례로 수행되는 sequential문으로 표현된다.
Process문의 구조는 다음과 같다.

[프로세스 레이블 : ]
process [(sensitivity_list)]
{선언문}
begin
{sequential문}
end process [프로세스 레이블];

2007/07/25

A Book On C Chapter 6 연습문제 7번.

만일 주소를 16진수 대신 10진수로 출력하여 보기 원한다면, 주소를 unsigned long으로 캐스트하고 %lu 형식을 사용하는 것이 안전한 방법이다. 연습문제 6번의 printf()문을 다음과 같이 수정하여 실행하여 보아라.

printf("%s%lu \n%s%lu \n%s%lu \n",
"&a = ", (unsigned long) &a,
"&b = ", (unsigned long) &b,
"&c = ", (unsigned long) &c);

명심하기만 하면 이 문제는 끝?

2007/07/24

A Book On C Chapter 6 연습문제 6번.

다음 프로그램은 %p 형식을 사용하여 어떤 주소들을 출력한다.

#include

int main(void)
{
int a = 1, b = 2, c = 3;
printf("%s%p \n%s%p \n%s%p \n",
"&a = ", &a,
"&b = ", &b,
"&c = ", &c);

return 0;
}

변수 a, b, c가 초기화되지 않았다면, 프로그램은 동일한 결과를 출력하겠는가?
%p를 %d로 수정하면, 어떻게 되겠는가? 컴파일러는 오류 메시지를 출력하겠는가?
가능하다면, 프로그램을 MS-DOS 시스템에서 실행해 보아라. 포인터는 4바이트이고 int는 2바이트이기 때문에, %d 형식은 적절하지 않을 것이고, 음수 값이 출력되는 원인일 수 있다.


실행결과
&a = 0x22cce4
&b = 0x22cce0
&c = 0x22ccdc
변수 a, b, c가 초기화되지 않더라도 동일함

%p를 %d로 수정해도 warnning이나 error은 발생하지 않음. MS-DOS 깔린 시스템이 요새 어딧나
확실히 %d 형식에선 오버플로/언더플로가 발생할 가능성도 있을것 같다.

2007/07/20

A Book On C Chapter 6 연습문제 5번.

변수가 선언되면, 그 변수들이 연속적인 메모리에 위치하는가? 다음과 같은 선언을 갖는 프로그램을 작성하여라.
char a, b, c, *p, *q, *r;
그리고 컴파일러에 의해 이 변수들이 배정된 메모리 위치를 출력하여라. 메모리 위치는 순서적인가? 만일 순서적이라면, 증가하는 순서인가 아니면 감소하는 순서인가? 각 포인터 변수의 주소는 4로 나누어지는가? 만일 그렇다면, 각 포인터 값은 기계 워드에 저장됨을 의미하는 것일 것이다.

메모리 위치는 4배수로 감소. 기계 워드는 4Byte(32Bit)를 의미하는것 같다.

2007/07/19

A Book On C Chapter 6 연습문제 4번.

i와 j는 int형이고, p와 q는 int형 포인터라면, 다음의 배정 수식 중 잘못된 것은 어느것인가?

p = &i : 장담하건데 퍼펙트한 수식이다.
p = &*&i : 장담하건데 퍼펙트한 수식이다.
i = (int)p : 또 장담하건데 퍼펙트하다. 둘 다 바이트수가 동일하니까
q = &p : int 형의 포인터의 포인터를 int 형의 포인터에 배정하는건 warning이지만 (int *)&p라면 퍼펙트할것이다.
*q = &j : int형의 포인터를 역참조한 곳에 int형의 주소값을 배정한다? int형에 int의 포인터를 배정한다는 건데 이건 warning을 만들어낸다.
i = (*&)j : (*&)은 아무런 의미가 없다. (+)j도 (-)j도 문법상 오류.
i = *&*&j : 퍼펙트
i = *p++ + *q : 퍼펙트

2007/07/18

A Book On C Chapter 6 연습문제 3번.

다음 프로그램을 보자.

#include
#include

int main(void)
{
int a, b, *p = &a, *p = &b;

ptrdiff_t diff = p - q;
printf("diff = %d\n", diff);


return 0;
}
ANSI C에서, 두 포인터 수식의 차는 부호있는 정수적형이어야 한다. 대부분의 UNIX 시스템에서 그 형은 int이고, 대부분의 MS-DOS 시스템에서 그 형은 long이다. 모든 ANSI C 시스템에서, 그 형은 표준 헤더 파일 stddef.h에 다음과 같은 형 선언으로 주어진다.
typedef type ptrdiff_t;
현재 사용하고 있는 시스템의 stddef.h에서 이 typedef를 찾아보면, diff의 형을 알게 될 것이다. diff가 int형이면 printf() 문에서 %d가 적절할 것이고, long 형이면 %ld가 적절할 것이다. 이 프로그램을 수행한 후 그 효과를 이해하여라. 그 후 프로그램에 다음과 같은 두 행을 추가하여라.
diff = p - (int *)0;
printf("diff = %d\n", diff);
기대했던 출력값이 나왔는가? 이것을 통해 연습문제 2번에서 논의한 컴파일러의 경고가 발생한 이유를 이해하겠는가? 설명하여라. 만일 int *를 ptrdiff_t *로 대치한다면, 프로그램은 다르게 동작하겠는가?


내 컴에 깔린 cygwin gcc를 확인해보면
#ifndef __PTRDIFF_TYPE__
#define __PTRDIFF_TYPE__ long int
#endif
typedef __PTRDIFF_TYPE__ ptrdiff_t;
ptrdiff_t는 long int 데이터 타입이다.
...
단순히 ptrdiff_t는 long 타입의 데이터 형이다.
포인터 연산 결과가 오버 플로우 되는것을 방지하기 위한건가?
포인터 연산의 결과는 데이터 형의 갯수로 평가되는데...굳이 이럴 필요가 없다고 생각되는데...
하긴 char 타입의 경우엔 필요할 수도 있겠군.
일단 여기까지만 생각.

2007/07/17

A Book On C Chapter 6 연습문제 2번.

컴파일러 중 어떤 것은 연습문제 1번의 수식 p - (p - 2)에 대하여 정수 오버플로에 관한 경고를 낸다. 연습문제 1번에서 작성한 프로그램을 수정하여 p와 p - 2 값을 출력하도록 하여라. 정수 오버플로가 발생하겠는가?(더 자세한 내용은 다음 연습문제를 참조하여라.)

#include
int main(void)
{
char *format = "%p %d %d %d %d %d\n";
int i = 3;
int *p = &i;
printf(format, p, *p + 7, 3 * **&p + 1, 5 * (p - (p - 2)), p, p - 2);

return 0;
}

출력은
0x22cce0 10 10 10 2280672 2280664

포인터 연산 시 '+'를 사용한다면 오버플로가 생길 가능성이 있어보인다.
'-'를 사용한다면 언더플로가 생길 가능성이 있을 것이고.

2007/07/16

A Book On C Chapter 6 연습문제 1번.

다음 코드를 실행시키면 4개의 값이 출력된다. 이것들 중 같은 값들은 몇 개인가?
답에 대해 설명하여라.

char *format = "%p %d %d %d\n";
int i = 3;
int *p = &i;
printf(format, p, *p + 7, 3 * **&p + 1, 5 * (p - (p - 2)));


printf("%p %d %d %d\n", p, *p + 7, 3 * **&p + 1, 5 * (p - (p - 2)));


- p : int 포인터 변수 p의 값. int 변수 i의 주소가 입력되있다.
- *p + 7 : int 포인터 변수 p를 역참조 후 plus 7. 3 + 7 = 10.
- 3 * **&p + 1 : int 포인터 변수 p의 주소값을 역참조 역참조 . 결국 int 포인터 i값을 가리킴. 3 * 3 + 1 = 10.
- 5 * (p - (p - 2)) : p - (p - 2) -> 2? 10일거라고 생각됨


Powered by ScribeFire.

2007/07/10

Entity

entity 선언부 및 architecture body로 이루어진다.
entity 선언부는 외부에서 이 컴포넌트가 어떻게 보일지를 기술한다.
architecture body는 해당 컴포넌트의 내부 모습을 RTL로 기술한다.

2007/07/09

A Book on C : function의 용도?


프로그램을 여러 개의 작은 함수들로 작성하는 데는 다음과 같은 몇 가지 중요한 이유가 있다.
한 가지 일만을 수행하는 작은 함수를 정확히 작성하는 것은 더욱 간단하다. 프로그램의 작성이나 디버깅 모두를 쉽게 할 수 있다. 이러한 프로그램은 유지와 수정도 더 쉽다. 수정이 필요 없는 코드들은 정확히 동작한다고 기대해도 되기 때문에, 수정이 필요한 함수들만 쉽게 수정할 수 있다. 또한 작은 함수는 그 자체로 문서화가 되고, 이해하기도 쉽다. 경험적으로 보면 각 함수를 한페이지 정도의 길이로 작성하는 것이 좋다.

Powered by ScribeFire.