블로그 이미지
JoyfulLife

공지사항

최근에 받은 트랙백

글 보관함

calendar

        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  

'C언어'에 해당되는 글 4

  1. 2011.08.25 교육3일차
  2. 2011.08.23 교육2일차
  3. 2011.08.23 교육1일차
  4. 2010.07.15 포인터

교육3일차

2011.08.25 00:22 | Posted by JoyfulLife
1. struct 은 call by value로 값을 전달한다.그래서 함수의 인자값으로 넘길 때 주소값으로 넘겨야 속도가 빠르다.
struct에서는 -> 연산자가 있다. 이것은 포인터 struct을 위한 연산자이다.

struct st
{
    int a;
    char b;
}x={10,'k};
struct st *p=&x;

라고 보자.

x.a == p->a; 는 값다.

sizeof(x) == 8


이제 배열의 등가 포인터를 보자.

2차원 배열을 보면 주소가 가리키는 타입이 중요하다는 것을 알 수 있다.

int a[3][4];

에서 a[0]이 가리키는 타입은 int*[4] 이다. a+1은 배열의 첫 요소의 ++ 이니 a의 주소의 + 4 이다.

 int (*  func(void)  )[4]
{
  static int a[3][4];
 return a;
}

void main()
{
   printf("%d",*(*(func()+1))+2);
}

가만히 보면 2차원 배열은 stack이 쌓이는 모습을 생각해야 한다. * 가 가리키는 곳과 *p+1 (*p)+1, *(p+1) 같은 것을 잘 분별해야 한다.


3.void * 는 단독으로 사용이 안되지만 어떤 타입이라도 받을 수 있다.

4.int *(*a[3])[4] 의 메모리 분석을 할 수 있을까?
a[0]과 *a[0]의 차이를 알 수 있는가?
a[0]은 int*(*)[4]를 가지고 있는 포인터이고, *a[0]은 배열을 int *[4]를 가리키는 배열이다. 때문에 *a[0]은 배열타입이다. 두 개의 값은 같지만 타입이 다르다.

5.오늘의 하이라이트 포인터 억세스 연습

#include<stdio.h>
char *c[]={"ENTER","NEW","POINT","FIRAT"};
char **cp[]={c+3,c+2,c+1,c};
char ***cpp=cp;

void main(void)
{
  printf("%s",**++cpp);
  printf("%s ",*--*++cpp+3);
  printf("%s",*cpp[-2]+3);
  printf("%s",cpp[-1][-1]+1);
}
를 푸는 것이다.
배열 안에 변수가 들어가서 좀 헷갈린다. 이것은 포인터의 개념을 확실히 알 수 잇는 문제인 것 같다.

스택을 그리고 분석을 해보자..






신고

'C언어' 카테고리의 다른 글

교육3일차  (0) 2011.08.25
교육2일차  (0) 2011.08.23
교육1일차  (0) 2011.08.23
포인터  (0) 2010.07.15
TAG C언어

교육2일차

2011.08.23 21:47 | Posted by JoyfulLife
오늘 교육은
int *(*a[4])(int *) ;
를 해석하는 방법을 배우는 것이다.
저걸 해석하면 a는 int의 주소를 리턴하는 함수의 주소 4개를 요소로 하는 배열이다. 고 한다.

후치 연산을 기본으로 하면 해석은 쉽게 된다. 하지만 저걸 어디서 쓰는지 보면 별 생각이 없어진다.
저건 배열이기는 한데  어떤 요소를 담고있냐고 하면,, 함수의 주소를 담고 있는데 그 함수는 int * 인자를 넘기고 return 으로 int * 를 넘긴다.

이 정도는 할만한다.

이제 & 연산자에 대해 알아보자.


int a[4]={10,20,30,40};
일 때
a=?
*a=?
&a=?
는 무엇일까?


a==&a[0] 으로 정의된다.
이정도하면 거의 되겠지..

&a는 무엇일까?  이것은 타입이 중요하다. 타입의 예외는 sizeof와 &연산자와 함께 쓰일때만 배열 타입이 된다. 나도 설명을 하고 있지만 잘 이해가 안가는 부분이다.

우선 넘어가자.. 나중에 a+1 같은 거 할 때 좀 더 자세히 알 수 있을 것이다.

int *p,*q;
p=(int *)0x1008;
q=(int *)0x1000;

p-q 는 offset 값이 나온다.  따라서 2이다 데이터 타입은 int이다. . 곱셈 나눗셈은 에러이다.


int a[4]={1,2,3,4}
에서 &a+1 의 값은 ?
int 형은 4바이트이다. &a는 배열이기 때문에 배열의 크기는 16바이트 이다.
+1은 16바이트만큼 증가를 한다. 저기서의 +1은 int형의 1이 아니고 배열 a의 크기만큼 하나를 증가하라는 의미이다. 데이타타입에 해당하는 가장 작은 단위 만큼 증가시키라는 의미이다.


(a+1)[2] 를 생각해보자.
이것은 *(a+3) 으로 변환이 가능하다. [] 의 연산자의 의미를 잠깐 살펴볼 수 있다.



오늘의 좀 이상한 문제인
char a[4]="LEW";
char *p=a;
p는 a를 가리킨다. &p는 p의 고유의 주소를 가리킨다.
a와 &a는 같은 값을 나타낸다.

printf("%X:%X","NEW",&"NEW");
는 어떻게 될까? 같은 값은 나타낸다.

NEW를 Text영역의 RO데이타에 저장하고 그 주소값을 보여주는 것이다.
기본과정에서 이런 상급 강의는 책에서 볼 수 없다. 왜냐하면 돈이 안되기 때문이다. 하지만 이런 메모리를 알면서 코딩을 해야지 문제점을 미리 파악할 수 있을 것이다.

int a[4];
a=(int *)0x2000;
는 에러가 난다.
그 이유는 a는 Lvalue 가 될 수 없기 때문이다.
Lvalue 는 왼쪽에 놓일 수 있는 값으로 a=1; 가 가능한 것을 말한다.
배열은 lvalue 가 될 수 없기 때문에 포인터를 활용해서 lvalue로 활용을 한다.
포인터는 indirect 로 주소를 참조하기 때문에 가능한 것이다.

char err[3][25]={"11111","22222","33333333333333"};

char *err[3][25]={"11111","22222","3333333333333333"};

를 비교해보자.
메모리로는 *err이 유리하고 속도면에서 err이 유리하다.


char e[25]="11111";
char *p=e;

e[0], *p 를 비교해보면 *p이 주소를 한번 더 참조를 해야 해서 속도가 느릴 것이다.

모.. 오늘은 이런 것을 배웠다.. 생각해보면 별로 배운것 이 없는데.. 8시간 동안 배운 것인데..



신고

'C언어' 카테고리의 다른 글

교육3일차  (0) 2011.08.25
교육2일차  (0) 2011.08.23
교육1일차  (0) 2011.08.23
포인터  (0) 2010.07.15
TAG C언어

교육1일차

2011.08.23 21:20 | Posted by JoyfulLife
형변환
형변환은 조금은 생각해봐야 할 문제이다.
char a;
int b=(int)a;

모 이런 식으로 해줄 수 있다. char 형은 1byte 이고 int는 4byte를 보통 많이 쓴다. 만약 a의 값이 0xff 라면 (int)a라고 했을 때 어떤 형식으로 될까?
0으로 채울 것이다.

다음으로 unsigned 와 singed 를 생각해봐야 한다.

unsigned char a=0x80;

printf("%u",a)
printf(%d",a)
는 어떤 차이를 보일까?

%u 는 인자를 unsigned int 로 간주를 한다.
%d는 signed int 로 간주를 한다.

답은 %d는 마이너스 값이 나올 것이다.


unsigned char a=0xff;

a==0xff 는 참일까? 거짓일까?

이걸 볼려면 비교되는 데이타 타입을 생각해야 한다. 데이타 타입이 같아야 비교가 가능하다.
0xff는 사실 0x000000ff 이다. 4바이트 인트형이니깐..
당연히 답은 참이다.

signed char a=0xff;
a==0xff 는 어떨까?
a는 무엇으로 변환이 될까? a는 -1 이다. 이걸 int형으로 변환하면 -1로 변환이 되는 것이다. 왜냐하면 signed이니깐..

데이터 타입을 맞추지 않은 사칙연산을 생각해보자.

int a; unsigned int b; char c;
a=c+b;

는 어떻게 될까? 이것은 c-> UI, c+b-> SI로 컴파일러가 자동으로 변환을 한다. 아마 경고문구는 나올 것이다.


float pi=3.14;

pi==3.14
는 참일까? 거짓일까?

3.14는 더블형이다. pi는 float 형이다. 이건 형변환이 일어난다고 해도 거짓일 것이다. 정확하게는 3.14가 2진수로 어떻게 표현이 되는지 생각해봐야 할 것이다. 3.14는 정확한 이진수가 안 나온다. 그래서 pi는 4바이트 double은 8바이트로 double 쪽에서 짤린다. 거기다가 floast 형과
double은 표현 방법은 달라서 float으로 실수를 표현하는 것은 안 좋다는 말이 많다.


다음은 static을 생각해보자.

static int a;
형은 a의 데이터가 stack에 저장되지 않고 memory에 저장이 된다.
이제는 변수가 어떻게 저장이 되는지도 생각해야 한다.


void main()
{
  f1();
  f1();
}
void f1()
{
   static int s=1;
   s++;
}
여기서 중요하게 생각해봐야 할 점은 static int s 이다.
s를 두 번 선언하는 것 같이 보인다. 하지만 컴파일러가 컴파일 할 때 static 을 보고 미리 메모리에 영역을 잡아 버린다. 따라서 실행될 때 선언되지 않고 가져다 쓰기만 한다.




c언어를 가볍게 생각을 했는데 메모리 부분까지 생각해봐야 하는 것 같다.


 
신고

'C언어' 카테고리의 다른 글

교육3일차  (0) 2011.08.25
교육2일차  (0) 2011.08.23
교육1일차  (0) 2011.08.23
포인터  (0) 2010.07.15
TAG C언어

포인터

2010.07.15 23:49 | Posted by JoyfulLife
포인터를 공부 중이다. 포인터 공부할수록 C언어는 포인터라고 생각이 든다.

지금은 포인터를 리턴하는 것을 배우고 있다.


(?) test() (?)
{
static int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
return a;
}

int main()
{
printf("%d", (?)test()(?));
}

7을 나오게 해보자.

함수의 리턴형은 더블 포인터인다.

단순하게

int ** test()

로하면 경고가 난다. a에 대한 것을 정확하게 리턴하지 못하기 때문이다.
타입이 일치해야지 경고가 나오지 않는다.

경고가 없이 리턴하는 법을 공부해보자.


타입의 일치가 씨언어에서 중요하다. 이것을 확실하게 알아야 한다.

static int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
a+1 = ?
*a+1 =?
**a+1= ?

&a+1 =?

어떻게 계산을 해야 하는가?

저것은 타입을 알아야 풀수 있는 문제이다.

답은
a+1= (a번지 + 16byte);
*a+1=(a번지 + 4byte);
**a+1=2;
&a+1=(a번지 + 48byte);


이것을 푸는 법은 나중에 설명을 하겠다.


그럼 맨 처음 답을 알아보자.

이것은 내가 예전에 배운 것이라 잘 생각이 안난다. 아마 배열을 사용한다면 좀 특별한 규칙이 들어간다.
변수는 선언문과 배열 사이에 존재한다는 규칙이었나?ㅡㅡ;;

아무튼...

정확한 리턴형을 찾아보자.

int ** 라고 생각하는게 일반적이다. 왜냐하면 배열은 포인터이니깐.

아. 다시 생각해보니 헷갈린다.

우선 답은 int (*test())[4] 이다.

이걸 풀어보자면 int(*)[4] test();

이다. 하지만 이것은 문법적인 규칙에 어긋나서 못 쓴다고 들었다. 그 문법에 대한 규칙이 무엇일까 공부를 해봐야 하겠다.


신고

'C언어' 카테고리의 다른 글

교육3일차  (0) 2011.08.25
교육2일차  (0) 2011.08.23
교육1일차  (0) 2011.08.23
포인터  (0) 2010.07.15
이전 1 다음

티스토리 툴바