20140328 (const, 2차원배열)

30일차

 

 

-------------

const

-------------

 

---------------------------

--- 포인터에 const가 붙으면?

 

int a = 10;

a = 40;  //  가능

const int b = 20;

b = 10;  // 불가능

int * c = &a;

*c = 20;  //  가능

c = &b;  //  불가능

cont int * d = &a;

*d = 30;  // 불가능

d = &b  //  가능

int * const e = &a;

*e = 40;  // 가능

e = &b  // 불가능

const int * const f = &a;

*f = 11;  //  불가능

f = &b;  //  불가능

 

 

 

----------------------------

2      차      원      배      열

----------------------------

 

- 전에 Arr[5] 이게 1차원 배열이라면

int iaArr[3][4]; 2차원 배열이라 부른다

 

--- 배열과 포인터의 관계

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

설정

트랙백

댓글

20140327 (포인터, 배열, call by address, call by value)

29일차

 

 

--------------------------------------

포    인    터      ,     배    열

---------------------------------------

 

---------------------------

--- 포인터 사용시 주의할 점.

 

int  iNum = 10;
double *  dpNum = &iNum;  // Warning!

double  dNum = 10.5;
int *  ipNum = &dNum;  
// Warning!

같은 포인터 타입이기에 Error는 안나서 실행은 되지만

다른 자료형(실수, 정수)이므로 Warning입니다.

상황에 따라 어떤 오류가 발생할지는 모르니 잘못된 것입니다.

 

int *  ipNum;

*ipNum = 1000// Warning!

ipNum에 주소값도 정해져 있지 않은데 그 주소값에 저장된 값을 바꾸면

어떤 문제가 발생할지 모르니 이것도 잘못된 것. warning, 런타임 에러

 

int *  ipNum = 1000;

*ipNum = 10;

ipNum에 1000번지를 넣었는데 1000번지가 어딘지 알고 넣었는지?

또 그 값을 변경도 시켰으니 Warning, 런타임 에러

 

int *  ipNum1 = 0;
int *  ipNum2 = NULL;

포인터는 NULL (0) 으로 초기화 값으로 주는게 좋다고 합니다.

그래서 아래 코드를 시험해 보니

#include <stdio.h>

int main()
{
  int *  ipNum = NULL;

  *ipNum = 10;

  return 0;
}

초기화 값을 뭘 주든 제대로된 주소가 아니면 런타임 오류가 납니다.

 

 

 

----------------

--- 포인터 연산

 

출력 화면

포인터를 연산할 경우 그 자료형 만큼 주소값이 움직입니다.

char * cpNum = 1000;

cpNum = cpNum + 2;    =>   1000 + 2 * 1byte   =>   1002   (2byte움직임)

int * ipNum = 2000;

ipNum = ipNum + 2;    =>    2000 + 2 * 4byte   =>   2008   (8byte움직임)

double * dpNum = 3000;

dpNum = dpNum + 2;    =>   3000 + 2 * 8byte    =>    3016   (16byte움직임)

 

 

 

-----------------------

--- *(ipNum+0) == arr[0]

 

배열도 포인터도 주소값을 저장하고 있어서

사용법도 비슷합니다. 그래서

*(ipNum+0) == arr[0]    <-- 이 등식이 성립합니다.

 

ex)

int main()
{
  int  arr[3= {112233};
  int *  ptr = arr;

  printf("arr[0] : %d \n", arr[0]);
  printf("arr[1] : %d \n", arr[1]);
  printf("arr[2] : %d \n", arr[2]);

  printf("ptr[0] : %d \n", ptr[0]);
  printf("ptr[1] : %d \n", ptr[1]);
  printf("ptr[2] : %d \n", ptr[2]);

  printf("*(arr + 0) : %d \n", *(arr + 0) );
  printf("*(arr + 1) : %d \n", *(arr + 1) );
  printf("*(arr + 2) : %d \n", *(arr + 2) );

  printf("*(ptr + 0) : %d \n", *(ptr + 0) );
  printf("*(ptr + 1) : %d \n", *(ptr + 1) );
  printf("*(ptr + 2) : %d \n", *(ptr + 2) );

  return 0;
}

출력 화면

*(ipNum+0) == arr[0]    <-- 이 등식이 성립합니다.

 

 

 

 

------------------------------------

--- char str1[] = "My String";
     char * str2 = "Your String";  장단점

 

여기서 str2 포인터 변수는 스택에 변수를 가리키는게 아니라

소스에 저장된 Your String을 가리킨다는 것을 명심!

 

배열

메모리 더 먹음, 수정 가능.

포인터

메모리 4byte만 먹음, 수정 불가.

 

 

 

 

 

--- 포인트 배열

포인트 타입의 배열이다.

ex)

arr 배열에 0, 1, 2 주소에 각각 주소값이 저장되어 있습니다.

printf("%d \n", *arr[0] );

->  printf("%d \n", *0x1000 );

->  printf("%d \n", 10 );

이런 과정을 거치겠죠....

 

 

 

 

--- 함수의 인자로 배열로 받을 수 없다.

그래서 포인터로 받는다.

ex)

 

 

 

 

 

--- Call by Address, Call by Value

함수에 인수를 다룰 때 쓰는 방법.

-   Call by Address     : 주소를 넘겨 호출.

-   Call by Value         : 을 넘겨 호출.

ex) 예제 소스

#include <stdio.h>

void CallByValue(intint);
void CallByAddress(int *, int *);

int main()
{
  int  iNum1 = 10;
  int  iNum2 = 100;

  CallByValue(iNum1, iNum2);  //  Call By Value
  printf("CallByValue() -> %d %d \n", iNum1, iNum2);

  CallByAddress(&iNum1, &iNum2);  //  Call By Address
  printf("CallByAddress() -> %d %d \n", iNum1, iNum2);

  return 0;
}

void CallByValue(int n1, int n2)
{
  int  iTemp;

  iTemp = n1;
  n1 = n2;
  n2 = iTemp;
}

void CallByAddress(int * n1, int * n2)
{
  int  iTemp;

  iTemp = *n1;
  *n1 = *n2;
  *n2 = iTemp;
}

출력 화면

 

CallByValue 는 말 그대로 main에 있는 변수의

가져와 쓰기 때문에 CallByValue 에서 무슨 짓을 해도

main의 변수에 접근할 수 없다.

 

CallByAddress 는 말 그대로 main에 있는 변수의 주소값

가져와 쓰기 때문에 CallByAddress 에서 무슨 짓이든

main의 변수에 접근할 수 있다.

 

 

 

설정

트랙백

댓글

20140326 (배열)

28일차

 

----------------

Array ( 배 열 )

----------------

- 배열 초기화

char caString[256] = "";

char caString[256] = {0};

둘다 0(NULL)로 초기화 된다.

 

 

- Call by Address, Call by Value

이것은 함수에 인수를 다룰 때 쓰는 방법이다.

Call by Address : 주소를 넘겨 호출.

Call by Value : 값을 넘겨 호출.

ex) 예제 소스

#include <stdio.h>

void CallByValue(intint);
void CallByAddress(int *, int *);

int main()
{
  int  iNum1 = 10;
  int  iNum2 = 100;

  CallByValue(iNum1, iNum2);  //  Call By Value
  printf("CallByValue() -> %d %d \n", iNum1, iNum2);

  CallByAddress(&iNum1, &iNum2);  //  Call By Address
  printf("CallByAddress() -> %d %d \n", iNum1, iNum2);

  return 0;
}

void CallByValue(int n1, int n2)
{
  int  iTemp;

  iTemp = n1;
  n1 = n2;
  n2 = iTemp;
}

void CallByAddress(int * n1, int * n2)
{
  int  iTemp;

  iTemp = *n1;
  *n1 = *n2;
  *n2 = iTemp;
}

출력 화면

CallByValue 는 말 그대로 main에 있는 변수의 값

가져와 쓰기 때문에 CallByValue 에서 무슨 짓을 해도

main의 변수에 접근할 수 없다.

CallByAddress 는 말 그대로 main에 있는 변수의 주소값

가져와 쓰기 때문에 CallByAddress 에서 무슨 짓이든

main의 변수에 접근할 수 있다.

 

 

- 여기서 잠깐 무시무시한 scanf()의 무서움을 보자.

ex) 예제 소스

#include <stdio.h>

int main()
{
  char  cStr[8];

  printf("문자열 입력 : ");
  scanf("%s", cStr);

  printf("입력 받은 문자열 : %s \n", cStr);

  return 0;
}

출력 화면

 

여기까지는 별 문제 없어 보인다.

하지만

입력한 문자가 9개를 넘어가면서 오류가 발생한다.

위에서 cStr[8] 크기를 8byte로만 지정했기 때문에

9byte (9글자)를 받았을때에 오류가 난다.

 

지금까지 scanf("%d", &iNum); 이렇게 항상 변수 앞에 &를 붙였는데

포인터를 배우면서 보았듯이 주소값을 넘겨주기 때문에

scanf() 함수에서 main함수의 변수를 만질 수 있었다.

그래서 그 이상의 값이 들어왔을때 오류가 나는 것을 볼 수 있다.

상위 버전 컴파일러로 컴파일시 scanf 함수 사용만으로도 warning을 출력한다고 한다.

그러니 지금은 scanf() 함수를 쓰지만 나중에 안정성을 위해

다른 함수를 사용해야할 것이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

설정

트랙백

댓글