[211105] 교육 5일차

oxllz·2022년 1월 22일
0

교육

목록 보기
5/41

포인터와 배열

배열

#include <stdio.h>
int main() {
	int l[4];
	int i, len;
	int* t;
//	
	l[0] = 3;
	l[1] = 6;
	l[2] = 5;
	l[3] = 8;
//	
	t = l;	
	// c 언어에서 배열의 길이를 재는 방법
	len = sizeof(l) / sizeof(int);	
	for( i = 0 ; i < len ; i++ ) {
		printf("%d\n", l[i] );
	}
	return 0;
}

배열형 변수는 포인터 변수에 대입 가능하다

// 포인터를 이용하여 배열의 합을 구하자1	
#include <stdio.h>
int main() {
	int l[4] = {3,6,5,8};
	int i, len, sum;
	int* t;
//	
	len = sizeof(l) / sizeof(int);
	// 포인터로 배열의 요소에 접근하기 
	t = l;
	printf("%d\n", *t );	 // 3
	printf("%d\n", *(t+0) ); // 3	
	printf("%d\n", *(t+1) ); // 5
	printf("%d\n", *(t+2) ); // 8
//	
	sum = 0;
	for( i = 0 ; i < len ; i++ ) {
		sum = sum + *(t+i);
	}
	printf("%d\n", sum );	
	return 0;
}
// 포인터를 이용하여 배열의 합을 구하자2 ( 함수 사용 )	
#include <stdio.h>
int sum(int* i , int j){
	int k;
	int total; 
	total = 0;	
	for(k = 0; k < j; k++){
    		// 포인터를 이용하여 배열의 요소에 접근
		total = total + *(i + k);
	}	
	return total;	
}
//
int main(){
	int l[4] = {3, 6, 5, 8};
	int sum2;
	int len;
	len = sizeof(l) / sizeof(int);
	// 포인터형 변수에 배열 대입가능
	sum2 = sum(l, len);	
	printf("%d\n", sum2);	
	return 0;
}

문자열

#include <stdio.h>
int main() {
	char l[6] = "Apple\0";
	char* t = "Hello\0";	
	printf("%s\n", l );
	printf("%s\n", t );
	return 0;
}

java 에서는 문자열을 다룰때 String 을 사용했다. C에서는 char[] 와 포인터를 사용한다.

문자열 이용시 배열에 할당된 공간 옆의 쓰레기값까지 보여질 수 있기에 모든 문자열은 반드시 \0 으로 끝나게 "" 안에 명시하는 것을 원칙으로 한다.

배열형 변수는 포인터에 대입 가능하니까 위와 같이 포인터로 문자열을 운용해도 같은 개념

#include <stdio.h>
#include <string.h>
int main() {
	char l[6] = "Apple\0";
	char* t   = "Hello\0";
	int len;
	// 문자열 배열의 길이를 잴 때는 이 방법은 적합하지 않다. ( \0 까지 포함 )
	len = sizeof(l) / sizeof(char);
	printf("%d\n", len );
    	// 문자열의 길이를 잴 때는 \0 은 고려하지 않아야 하기 때문에 strlen 함수를 쓴다.
	printf("%d\n", strlen(l) );
	//
	if( 0 ) {
		printf("Apple");
	}
	return 0;
}

java 는 boolean 이라는 자료형이 있다. if( ... ) 안에는 boolean 값 true/false 만 가능하고 비교연산( > < >= <= == != )의 결과는 boolean 값으로 나온다.

C에서의 true/false

  • c 는 기본적으로 boolean 자료형이 없다. 그래서 조건에 정수형을 쓰는데 0 은 false , 0 이 아니면 true 로 사용한다.
#include <stdio.h>
int main() {
	char* t = "HelloWorld\0";
	int i;	
	for( i = 0 ; *(t+i) ; i++ ) {
		printf("%c\n" , *(t+i) );
	}
	return 0;
}
출력결과
H
e
l
l
o
W
o
r
l
d
char* t = "HelloWorld\0";

위의 코드에서 \0 은 실제로 문장의 일부가 아니라 0이라는 값을 의미하는 특수한 표현식이다. ( NULL 문자라고 한다. ) 그렇기때문에 출력되지 않는다.

클로저

#include <stdio.h>
int* temp() {
	int i;
	i = 100;	
	return &i;
}
//
int main() {
	int *t;
	t = temp();
	printf("%d\n", *t );
	return 0;
}

위의 코드는 뭐를 잘못해서 경고가 떴을까 ?

  • 클로져 ( Closure ) 개념이 나타남 : 즉 다른 곳에서 포인터로 가리키는 로컬변수는 살리자!

'이런 코드는 안 짜는게 좋은데 그럼 대안이 뭘까?'

#include <stdio.h>
int* temp_N() {
	int* i;
	i = (int*)malloc(sizeof(int));
	*i = 100;
	return i;
}
int main() {
	int *t;
	t = temp_N();
	printf("%d\n", *t );
	free( t );	
	return 0;
}

개념적으로는 완벽한데 , temp() 함수를 호출하는 사람들은 포인터 활용 후 반드시 free() 를 호출해야 한다는 사실을 알고 있어야 한다.

따라서 함수이름의 맨 뒤에 _N 을 붙인다. 그건 내부에서 malloc 된 메모리의 포인터를 돌려주는 형태의 코드라는 의미. ( 바다 OS에서 쓰던 삼성스타일 코드 네이밍 원칙 )


구조체

구조체

struct apple {
	int name;
	int value;
};
//
int main() {
	struct apple i;
	i.name  = 100;
	i.value = 200;
    	// 하나의 변수에 두개의 값 저장
	printf("%d %d\n", i.name , i.value );
	return 0;
}

구조체 : 새로운 타입 ( 복합형 )의 자료형을 선언한 것으로 일단 생각하자. 자료형은 하나의 값만 대입 가능했지만 구조체로 선언된 변수는 여러개 값을 담을 수 있다.

구조체 포인터

#include <stdio.h>
struct apple {
	int name;
	int value;
};
//
int main() {
	struct apple i;
	struct apple* t;
//	
	t = &i;
//	
	t->name  = 100;
	t->value = 200;
	printf("%d %d\n", t->name, t->value );
	return 0;
}
t->name = 100

't 라는 포인터가 가리키는 구조체형 공간 안의 name 이름으로 확보된 공간' 에 100을 대입한다.

구조체에 변수이름으로 접근할때는 . 을 쓰고, 포인터로 접근할때는 -> 을 쓴다.

#include <stdio.h>
struct apple {
	int name;
	int value;
};
//
int main() {
	struct apple* t;
//
	t = (struct apple*)malloc(sizeof(struct apple));
	t->name = 100;
	t->value = 200;
	printf("%d %d\n", t->name, t->value);
//	
    free( t );
	return 0;
}

구조체로 변수와 포인터를 선언할 수 있다.

0개의 댓글