본문 바로가기

컴퓨터 일반/프로그래밍언어론

프로그래밍(4) C언어 포인터, 배열

포인터

포인터란 주소의 주소입니다

오늘 길동이 집으로 모여, 그 길동이가 변수라고 생각하면 돼요.

야, 서울시 oo동 oo번지로 모여 이렇게 말할 수도 있습니다

c언어는 이렇게 주소를 사용할 수 있고 주소를 담을 수 있는 변수가 포인터입니다

(자바는 포인터를 처리하지 않습니다)

포인터는 주소이고, 주소를 담을 수 있는 변수를 포인터 변수라고 합니다.

  • 포인터 변수를 선언할 때는 자료의 형을 먼저 쓰고 변수명 앞에는 *를 붙인다
  • int *b; //b라는 변수는 이제 일반 숫자가 아닌 포인터(주소)를 담을 수 있는 정수형 변수이다
  • char *c; //c라는 변수는 이제 포인터를 담을 수 있는 문자형 변수이다
  • int a;는 기억 장소 어딘가에 가서 만들어진다, 주소를 알고 싶으면 &a로 알 수 있다
  • int *b; int a; b = &a; //a의 주소를 포인터 변수인 b에 넣은 것이다
  • int a = 100; //a가 있는 곳에 데이터 100이 저장됨
  • b = &a; //b에 a의 주소가 저장됨
  • 실행문에서 포인터 변수에 *를 붙이면 해당 포인터 변수가 가리키는 곳의 값을 말한다
  • 즉 포인터 변수가 가리키고 있는 주소의 값이다.
  • *b = *b + 10 //실행문이 가리키는 곳의 값에 10을 더한다. 4번지에 있는 값이 100이라면 110이 된다.
  • 포인터 변수b가 가리키는 곳의 값을 바꾸면 해당 a의 값도 바뀐다
  • 주소를 찍을땐 %p 이다
int a;
int *b;
a = 100; //4번지에 100 저장됨
b = &a; //4가 기억됨
b = *b + 10;//포인터 변수가 가리키는 곳의 값을 말할 때는 *를 붙인다, 즉 110이다

https://www.youtube.com/watch?v=DQwCg32yT5k&list=PLpYNFXUfkvDomFmLaDEVtwDs7e9NhT_j2&index=81

여기서 변수 a의 값은 20이었지만 가리키는 포인터 변수b가 30이 되어 a의 값도 30으로 변경되었다

 

배열

array, 말 그대로 나열 시킨 것인데 기억 장소에 형과 크기가 같은 것을 여러개 모아서 한번에 쓰는 것이다.

프로그램 하다보면 변수가 수백개 수천개 쓰일 때가 있다

ex. 한 반의 학생 40명일때 변수를 40개 써야한다

하지만 똑같은 형의 변수이니까 배열을 만들어서 위치만 가리키게 하는 것이다.

1차원 배열은 변수들을 일직선상의 개념으로 조합한 배열이다

자료형 변수형[개수]

  • int a[5]
  • 자료형 : 배열에 저장할 자료의 형을 지정한다
  • 변수명 : 사용할 배열의 이름이므로 사용자가 임의로 정한다
  • 개수 : 배열의 크기를 정한다
  • 선언할 때 a에 5개라고 선언했으니까 정수 배열이고 5개의 요소를 갖는 배열이다
  • 쓸 때는 0번지부터 쓴다, a[4] 라면 다섯번째 요소이다
  • 배열은 반복문과 관련이 깊다

프로그램 자체가 사람이 어떻게 하면 쉽게 쓸까를 생각하고 만들었기 때문에 실제로는 어렵지 않다

반복분이 두개이면 한 반복문을 완료하면 다음 반복문을 수행한다 (for 다음에 for)

 

배열의 이름은 주소다, 주소를 이용해서 배열의 결과를 찍어본다.

  • 메모리 어딘가에 변수 a, i, p가 생겼다
  • 정수형은 4바이트이기 때문에 100번지라면 100 104 108 112 116…이렇게 증가한다
  • p = a; //a는 배열이다, 배열은 주소다
  • p는 정수를 담을 수 있는 포인터 변수이다. a의 주소를 p가 가리키게 된다 (100번지)
  • 실행문에서 *는 그것이 가리키고 있는 곳의 값이다.
  • p는 100이고 i는 0, *100은 10이다
  • 포인터 변수는 포인터 단위(주소 단위)로 움직인다, 그래서 i가 증가하면 포인터 변수는 그 다음 번지를 가리킨다, 4바이트가 증가한다
  • 즉 포인터 변수를 증가시키면 다음 번지를 가리킨다
  • p는 계속 100번지를 가리키고 i가 증가하면서 다음 번지를 가리키므로 100번지 → 104번지 → 108 번지…
  • 10 → 11 → 12…
  • 포인터가 증가한다는 것은 그 자료형의 크기만큼 증가한다. 정수형이니까 4바이트씩 증가한다, 문자형이라면 1바이트씩 증가한다

 

2차원 배열

1차원 배열은 직선적인 구조인데

2차원 배열은 1차원 배열이 여러개 있는 것을 하나도 묶은 것이다(행과 열)

  • 변수들을 평면, 즉 행과 열로 조합한 배열이다
  • 자료형 변수명[행개수][열개수]
  • int a[3][4] //3행 4열
0,0 0,1 0,2 0,3
1,0 1,1 1,2 1,3
2,0 2,1 2,2 2,3

 

안쪽 반복문 반복 → 바깥쪽 반복문 반복

i j k 결과
0 0 1 [0][0]=1
  1 2 [0][1]=2
  2 3 [0][2]=3
  3 4 [0][3]=4
1 0 5 [1][0]=5
  1 6 [1][1]=6
  2 7 [1][2]=7
  3 8 [1][3]=8
2 0 9 [2][0]=9
  1 10 [2][1]=10
  2 11 [2][2]=11
  3 12 [2][3]=12

 

사용자 정의 함수

말그대로 사용자가 만들어서 쓰는 함수이다, 필요한 기능을 만들어서 쓸 수 있다

(기본적으로 만들어져 있는 함수는 내장 함수이다)

  • 프로그램은 위에서부터 밑으로 실행된다
  • 프로그램은 main()을 만나야만 실행된다
  • 즉 위에서부터 내려오는데 위에서 내가 만든 함수를 선언해놓고 아래에 정의하면 main()함수 안에서 사용할 수 있다
  • 아래는 리턴 값이 없는 경우 -> 돌려주는 값이 없음
  • 리턴 값이 있는 경우 -> 돌려주는 값이 있음
  • #include <stdio.h>
    void func(int i, int j); //내가 쓸 함수를 선언, 함수의 리턴값이 없으면 void
    						//func 함수는 정수형 변수 i,j를 받는구나
    main()
    {  
    		int a = 3, b = 12;
    		func(a,b); //이 함수가 어딘가에 반드시 있어야 한다
    	printf("%d, %d", a,b);
    		}
    
    void func(i, j) 
    int i,j;
    { 
    	i*=3;
    	j /=3;
    	printf("%d, %d", i,j);
    	//나를 부른 곳으로 돌아간다
    	}
    	
    	//정의한 함수는 리턴값이 없다
    	//9,4 
    	//3,12가 출력된다
#include <stdio.h>
func(i,j); //앞에 void가 없다 = 리턴 값이 있다
main()
{
	int a = 3, b = 12;
	a = func(a,b);
	printf("%d, %d", a,b);
	}
	
func(i, j)
int i, j;
	{
		i *= 3;
		j /= 3;
		printf("%d, %d", i,j);
		return i; //i 값을 돌려준다
		//나를 부른 곳으로 돌아간다
		}
	
	//a=9, b=12
	//리턴 값은 하나만 돌려줄 수 있다
	//여러개를 돌려주려면 주소 값을 이용한다

 

 

값을 여러개 돌려줘야 하는 경우는 구조체를 만들거나 주소를 이용한다.

주소(포인터 변수)로 그곳의 값을 바꿔버리면 된다, 포인터를 사용한다

#include <stdio.h>
void func(int *i, int *j); //리턴값이 없고 포인터 변수를 두개 받는 함수
main() 
{
	int a=3, b=12;
	func(&a, &b); //번지를 가리킨다
	printf("%d, %d", a,b);
	}

void func(i,j)
int *i, *j; //정수형 변수의 주소를 가진다
{
	*i *= 3; //*i는 i변수가 가리키는 값, 여기에 3을 곱한다 = 9
	*j /= 3; //*j는 j변수가 가리키는 값, 여기에 4를 나눈다 = 4
	printf("%d, %d", *i, *j);
	}

 

 

내장 함수

이미 정의가 되어 있는 함수이며, 헤더파일을 작성하고 사용한다

pow(x,y) 거듭제곱 pow(2,5)=32
sqrt(x) 제곱근 sqrt(25)=5
abs(x) 절대값 abs(-70)=70
strlen(a) 문자열 길이 strlen(”abcd”)=4
strcpy(a,b) 문자 배열 복사  
strcmp(a,b) 문자열 비교 같다면 0을, a가 크면 1을, b가 크면 -1을 반환한다
atoi(a) 문자열->정수형 atoi(”12”) → 12가 된다
atof(a) 문자열→실수형  
#include <stdio.h>
#include <string.h>
#include <math.h>
main()
{
printf("%f", pow(2,3));
printf("%f", sqrt(25));
printf("%f", abs(-32));

char a[] = "ad";
char b[] = "ac";
printf("%d", strcmp(a,b)); //1 (b가 크다) 
srtcpy(a,b); //b를 a에 복사 -> ac가 된다
printf("%d", strcmp(a,b)); //0 (둘은 같다)

char c[]="123";
char d[] ="456";
printf("%d",atoi(c) + atoi(d)); //579

char e[]="12.3";
char f[] ="45.6";
printf("%f",atof(e) + atof(f)); //57.9