'Programming/C'에 해당하는 글 22건

반응형
별표 하나는 대괄호 하나에 해당한다.
2차원 배열을 포인터로 접근했을 때 별(*)표 하나는 행을 대상체로 하므로 배열 요소 자체의 값을 구할 수 없다.
포인터 변수 더하기 정수는 행 단위로 움직인다.

/* *( imsip + 1 ) 과 *imsip + 1의 차이 */
#include <stdio.h>
main() {
  int imsi[ 2 ][ 3 ] = { { 3, 5 }, { 12, 54 }, { 534, 923 } };
  int ( *imsip )[ 2 ];

  imsip = imsi;

  printf( "%#010x %#010x\n", *imsip, *imsip + 0 );
  printf( "%#010x %#010x\n", *( imsip + 1 ), *imsip + 1 );
  printf( "%#010x %#010x\n", *( imsip + 2 ), *imsip + 2 );
}
// output
0x8047d10 0x8047d10
0x8047d18 0x8047d14
0x8047d20 0x8047d18

*imsip, *imsip + 0 은 차이가 없다.
*( imsip + 숫자 ) 는 imsip + 숫자와 같고 이는 행 단위로 움직인다.
*imsip + 숫자는 배열 요소의 증가를 뜻하므로 4바이트씩 증가한다.

int imsi[ 2 ][ 3 ] = { { 3, 5 }, { 12, 54 }, { 534, 923 } };
int ( *imsip )[ 2 ];

imsip = imsi;

// 다음 포인터 변수를 사용하여 출력
printf( "%d\n", *( *( imsip + 0 ) + 0 ) );  // 3
printf( "%d\n", *( *( imsip + 0 ) + 1 ) );  // 5
printf( "%d\n", *( *( imsip + 1 ) + 0 ) );  // 12
printf( "%d\n", *( *( imsip + 1 ) + 1 ) );  // 54
printf( "%d\n", *( *( imsip + 2 ) + 0 ) );  // 534
printf( "%d\n", *( *( imsip + 2 ) + 1 ) );  // 923
// 가장 안쪽의 괄호 안의 수치는 행, 바깥쪽은 행의 배열 요소와 관련

// 다음과 같이 변경 가능
printf( "%d\n", *( imsip[ 0 ] + 0 ) );  // 3
printf( "%d\n", *( imsip[ 0 ] + 1 ) );  // 5
printf( "%d\n", *( imsip[ 1 ] + 0 ) );  // 12
printf( "%d\n", *( imsip[ 1 ] + 1 ) );  // 54
printf( "%d\n", *( imsip[ 2 ] + 0 ) );  // 534
printf( "%d\n", *( imsip[ 2 ] + 1 ) );  // 923

// for문 사용
for ( i = 0; i < 3; i++ )  // 행의 길이
  for ( j = 0; j < 2; j++ ) { // 열의 길이
   printf( "%d\n", *( imsip[ i ] + j ) );
  }
}


int ( *imsip )[ 2 ] vs int *temp[ 2 ]

#include <stdio.h>
main() {
  int ( *imsip )[ 2 ];
  int *temp[ 2 ];

  printf( "&imsip %#010x\n", &imsip );
  printf( "&temp[ 0 ] %#010x\n", &temp[ 0 ] );
  printf( "&temp[ 1 ] %#010x\n", &temp[ 1 ] );
}
// output
&imsip 0x8047d24
&temp[ 0 ] 0x8047d18
&temp[ 1 ] 0x8047d1c

temp 라는 것은 포인터를 저장할 수 있는 영역이 두 개인 것이다. (temp[ 0 ], temp[ 1 ])
그리고 temp 자체는 배열명이 된다.
반응형

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret
반응형
배열 포인터 정의

int *imsip;  // 1차원 배열 포인터
int (*imsip2)[ 3 ];  // 2차원 배열 포인터
int (*imsip3)[ 2 ][ 3 ];  // 3차원 배열 포인터

/* 1차원 배열의 sizeof */
#include <stdio.h>
main() {
  int imsi[ 2 ];
  int *imsip;

  printf( "%d\n", sizeof( imsi ) );  // 8
  printf( "%d\n", sizeof( imsip ) );  // 4
  printf( "%d\n", sizeof( *imsip ) );  // 4
}
.
/* 2차원 배열의 sizeof */
#include <stdio.h>
main() {
  int imsi[ 2 ][ 3 ];
  int ( *imsip )[ 3 ];

  printf( "%d\n", sizeof( imsi ) );  // 24
  printf( "%d\n", sizeof( imsip ) );  // 4
  printf( "%d\n", sizeof( *imsip ) );  // 12
}

*imsip 가 가리키는 대상체는 imsi[ 0 ][ 0 ] 하나가 아니라
imsi[ 0 ][ 0 ], imsi[ 0 ][ 1 ], imsi[ 0 ][ 2 ]이다.
( *imsip )[ 3 ] 에서 첨자에 사용된 3이라는 수치가 이를 나타내고 있다.
2차원 배열 포인터 변수의 배열 첨자는 열의 개수이다.

#include <stdio.h>
main() {
  int imsi[ 2 ][ 3 ] = { { 3, 5 }, { 12, 54 }, { 534, 923 } };

  printf( "%d byte\n", sizeof( imsi ) );  // 24
  printf( "%d byte\n", sizeof( imsi[ 0 ] ) );  // 8
  printf( "%d byte\n", sizeof( &imsi[ 0 ][ 0 ] ) );  // 4
}

imsi, imsi[ 0 ], &imsi[ 0 ][ 0 ] 는 확실히 같은 번지를 가리킨다.
하지만 가리키는 대상체의 크기가 다르다는 것을 위 예문에서 보여준다.
imsi 는 배열 전체를 가리키고 있다. ( 24 byte가 증명 )
imsi[ 0 ] 는 행을 대표하고 있다. ( 8 byte가 증명 )
&imsi[ 0 ][ 0 ] 는 하나의 배열 요소를 가리키고 있다.

int imsi[ 3 ] = { 5, 3, 7 };
int *imsip = imsi;

int imsi2[ 3 ][ 2 ] = { 7, 3, 2, 5, 3, 8 };
int (*imsip2)[ 2 ];

imsip 는 imsi 배열의 첫번째 요소를 가리킨다.
5, 3, 7 전부를 가리키는게 아니라 5만 가리킨다.
2차원 포인트 변수인 imsip2 는 2차원 배열이기 때문에 요소의 행을 가리킨다.
imsip 가 가리키는 대상은 4바이트고 imsip2 는 8 바이트이다.
반응형

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

배열의 초기화

Programming/C 2006. 10. 24. 20:21
반응형
1차원 배열

#include <stdio.h>
main() {
  int imsi[ 3];

  imsi[ 0 ] = 0;

  printf( "%d %d %d", imsi[ 0 ], imsi[ 1 ], imsi[ 2 ] );
}
// output
0 -541085696 -541125761

위 예를 보면 배열이 어떤 값을 저장할 수 있는지를 지정하는 타입이 있다.
배열의 첨자를 이용하여 배열의 개수도 지정한다.
배열의 첨자는 0부터 시작하므로 정의할 때 첨자 수와 사용할 때 첨자 수는 -1의 오차를 보인다.
imsi[ 1 ], imsi[ 2 ]는 초기화를 하지 않았으므로, 어떠한 값이 들어가 있을지 아무도 모른다.
다음의 두가지 방법은 imsi 배열을 초기화 시켜준다.

for ( i = 0; i < 3; i++ ) {
  imsi[ i ] = 0;
}

int imsi[ 3 ] = { 0 };

다음과 같이 첨자를 생략할 수도 있다.

int imsi[] = { 4, 3, 7, 4 };

위 문장을 만나는 순간 컴파일러는 초기치의 개수를 세고 이를 첨자에 반영한다.
imsi의 첨자는 자동을 4가 되고 16바이트가 할당된다.


다차원 배열

다차원 배열은 다음처럼 할 수 있다.

int imsi2[ 2 ][ 3 ];
int imsi3[ 2 ][ 3 ][ 4 ];
int imsi4[ 2 ][ 3 ][ 4 ][ 5 ];

#include <stdio.h>
main() {
  int imsi[ 2 ][ 3 ] = { 0 };

  printf( "%d %d %d %d %d %d", imsi[ 0 ][ 0 ], imsi[ 0 ][ 1 ], imsi[ 0 ][ 2 ], imsi[ 1 ][ 0 ], imsi[ 1 ][ 1 ], imsi[ 1 ][ 2 ] );
}
// output
0 0 0 0 0 0

다차원 배열의 초기화 방법

int imsi[ 2 ][ 3 ] = { { 1, 2, 8 }, { 34, 634, 7 } };
int imsi[ 2 ][ 3 ] = { 1, 2, 4, 2, 34, 634 };
// 빈공간은 0으로 초기화
int imsi[ 2 ][ 3 ] = { { 1, 2, 8 }, {} };
int imsi[ 2 ][ 3 ] = { 1, 2, 8 };
int imsi[ 2 ][ 3 ] = { {}, 4, 7, 3 };
int imsi[ 2 ][ 3 ] = { {}, { 4, 7, 3 } };


1차원 배열과 포인터

배열명은 배열의 첫번째 배열요소의 주소를 뜻한다.
배열명은 포인터 변수가 아니라 배열명 자체임을 명심하라.

#include <stdio.h>
main() {
  int imsi[ 3 ] = { 5, 3, 7 };
  int *imsip;

  imsip = imsi;

  printf( "%#010x %#010x %#010x\n", imsi, &imsi[ 0 ], imsip );
}
// output
0x8047d1c 0x8047d1c 0x8047d1c


포인터 + 정수

주소값 + 정수값 = 주소값이다.
포인터 변수에 정수값을 더할 때 정수 값 만큼의 바이트가 더해지는게 아니라 포인터 변수의 타입 크기만큼 증가한다.
그러므로 배열의 주소값에 + 정수값을 하면 다음 첨자 값을 얻을 수 있다.

#include <stdio.h>
main() {
  int imsi[ 3 ] = { 5, 3, 7 };
  int *imsip;

  imsip = imsi;

  // 더하기(+) 보다 역참조 연산자(*)의 우선순위가 높으므로 괄호를 사용
  printf( "%d, %d, %d", *( imsip + 0 ),  *( imsip + 1 ),  *( imsip + 2 ) );
}
// output
5 3 7
반응형

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret

포인터 변수

Programming/C 2006. 10. 23. 17:57
반응형
포인터

포인터는 번지에 대한 기호화된 표현을 말한다.

int imsi;

imsi라는 변수를 정의한 문장을 만나면 시스템은 imsi에 대하여 4바이트의 메모리를 할당한다.
시스템이 할당해 준 4바이트는 다른 프로세스들이 할당받지 못하므로 안전하게 사용할 수 있다.
4바이트는 모두 번지라고 하는 이름을 가지고 있고, 일반적으로 4바이트 형식으로 표현된다.

int imsi (4byte)
1byte : 0x8047c70
1byte : 0x8047c71
1byte : 0x8047c72
1byte : 0x8047c73

결국 포인터라는 것은 메모리의 위치를 표현한 기호인 것이다.


포인터 변수

포인터 변수는 포인터를 저장할 수 있는 변수를 말한다.
이 말은 메모리의 특정 위치를 저장한다는 말과 같다.
포인터 변수에는 번지 이외에는 그 어떤 것도 들어갈 수 없다.

int *imsip;

imsip라는 정수형 변수에 *을 붙였다.
imsip는 정수를 저장하는 곳이 아니라, 정수가 저장된 곳의 위치을 기억하게 된다.
포인터 변수 imsip에는 오로지 번지만 들어갈 수 있으므로 숫자나 문자열 등을 할당할 수 없다.

main() {
  int *imsip;

  printf( "%p\n", imsip );  // imsip 에 저장된 값 출력
  printf( "%p\n", &imsip );  // imsip 가 할당된 메모리 주소 출력 (0x8047c64 등의..)
}


& 연산자

포인터 변수에 번지 값을 저장하기 위해 '&' 연산자가 필요하다.
&는 '앤드 연산자', '번지 연산자' 하고 하며, 어떤 변수가 저장된 곳의 선두 번지를 뜻한다.

#include <stdio.h>

main() {
  int imsi = 5;

  printf( "imsi[ %d]\n", imsi );
  printf( "&imsi[ %#010x]\n", &imsi );
}
// output
imsi[ 5]
&imsi[ 0x8047d24]


포인터 변수에 번지 할당

#include <stdio.h>

main() {
  int imsi;
  int *imsip;

  imsip = &imsi;
}

imsip 라는 포인터 변수에 imsi 가 저장된 곳의 주소를 넣고 있다.
& 연산자가 특정 변수의 선두 번지를 뜻한다면, * 연산자는 포인터 변수에 저장된 선두 번지를 참조하여 하나의 값을 취한다.

#include <stdio.h>

main() {
  int imsi = 5;
  int *imsip;

  imsip = &imsi;
  printf( "*imsip[ %d]\n", *imsip );
}
// output
*imsip[ 5]
&imsi == imsip == &*imsip
.
#include <stdio.h>

main() {
  int imsi = 5;
  int *imsip;

  imsip = &imsi;
  *imsip = imsi;  // * 역참조 연산자 (deferencing operator)
  printf( "imsip[ %#010x] *imsip[ %d]\n", imsip, *imsip );
}
// output
imsip[ 0x8047d24] *imsip[ 5]
.
#include <stdio.h>

main() {
  int imsi = 5;
  int *imsip;

  imsip = &imsi;
  *imsip = *imsip + *imsip;
  printf( "%d\n", *imsip );  // output: 10
  printf( "%d\n", imsi );  // output: 10
}


포인터 변수 타입

int  *intp;
float  *floatp;
double  *doublep;
char  *charp;

포인터 변수 타입은 메모리에 4바이트가 할당된다.
그렇다면 위와 같은 포인터 변수에 왜 타입이 필요한가?
포인터 변수의 타입은 변수가 가리키는 곳으로 번지로 가서 몇 바이트를 읽어오는가에 대한 답을 주는 것이다.
반응형

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  1개가 달렸습니다.
  1. 위 출력양식 '%#010x' 에서 '#'는 출력시 16진수임을 알리기 위해 '0x'를 붙이라는 말임.
secret

Pointer & Array

Programming/C 2006. 10. 4. 11:51
반응형
포인터와 배열 (Pointer & Array)

배열에 의한 연산은 포인터를 사용해서 할 수 있다.
포인터를 사용하는 것이 더 빠르다.

int a[10];  // 크기가 10인 배열
int *pa;  // 정수형 포인터

pa = &a[0];  // pa는 a[0]의 포인터
x = *pa  // x는 a[0]과 같은 값
*(pa + 1)  // a[1] 과 같음

a[i]는 *(a + i)와 같다.


번지 연산

/* 포인터의 뺄셈 - 문자열 길이 반환 */
int strlen( char *s ) {
  char *p = s;  // p 초기화 - s 문자열의 처음을 가리킴
  while ( *p != '\0' )
   p++;
  return p - s;  // 비교한 문자의 개수, 문자열의 길이를 나타냄
}

포인터에 대한 정수를 더하거나 뺄 수 있다.
포인터를 0과 비교할 수도 있고 같은 배열내의 두 포인터를 비교할 수도 있다.
포인터에 포인터를 더하거나 뺄 수는 없다.
포인터에 실수를 더하거나 빼서도 안되며 포인터에 곱셈이나 나눗셈을 해서도 안된다.
포인터에는 비트연산을 해서도 안된다.
cast 연산자 없이 어떤 형의 포인터를 다른 형의 포인터로 사용하면 안된다.(void예외)
반응형

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

트랙백  0 , 댓글  0개가 달렸습니다.
secret