[211108] 교육 8일차

oxllz·2022년 1월 24일
0

교육

목록 보기
6/41

C

Linked List

#include <stdio.h>
typedef struct abcd {
	int name;
	struct abcd* next;
} Node;
//
int main() {
	Node* head;
	Node* tail;
	Node* temp;
	Node* post;
	Node* pre;
	// 초기상황
	head = (Node*)malloc(sizeof(Node));
	tail = head;
	head->name = 0;
	head->next = NULL;
	// 10 이 생기고 붙음
	temp = (Node*)malloc(sizeof(Node));
	temp->name = 10;
	temp->next = NULL;
	tail->next = temp;
	tail = temp;	// tail->next 도 가능 ( 같은 얘기 )
	// 20 이 생기고 붙음	
	temp = (Node*)malloc(sizeof(Node));
	temp->name = 20;
	temp->next = NULL;
	tail->next = temp;
	tail = temp;
	// 10 20 출력
	for( temp = head->next ; temp != NULL ; temp = temp->next ) {
		printf("%d\n", temp->name );
	}
	// 앞에서 부터 차례로 삭제하고 초기상황으로 돌림
	post = head;
	pre = head->next;
	while( pre != NULL ) {
		post = pre;
		pre = pre->next;	
		free( post );
	}
	tail = head;
	free( head );
	return 0;

typedef : 사용자가 정한 자료형 ( struct abcd 를 Node 로 줄여서 쓰는 효과 )
모든 포인터 변수에는 NULL 이 대입가능. '아무것도 가리키지 않는다'

1) (Node*)malloc(sizeof(Node)) 생성
2) temp = (Node*)malloc(sizeof(Node)); temp가 가리키게 한다.
    temp->name = 10; 
    temp->next = NULL;
    값 대입
4) tail->next = temp;
   tail = temp;	// tail = tail->next 도 가능 
   앞 노드와 뒷노드를 연결시켜주고 tail이 마지막 노드를 가리키게 한다.

post = head;
pre = head->next;
while( pre != NULL ) {
	post = pre;
	pre = pre->next;	
	free( post );
}
tail = head;
free( head );

함수포인터

#include <stdio.h>
int add( int i, int j ) {
	return 100;
}
//
int main() {
	int (*fp)( int, int );	// 함수포인터	
	fp = add; // fp 라는 포인터는 add 라는 함수를 가리킨다.
	printf("%d\n", fp( 10,20 ) );	// fp 가 가리키는 함수가 호출된다.
	return 0;
}
int (*fp)( int, int )

매개변수가 int, int 이고 리턴타입이 int 인 함수를 가리킬 수 있다.

#include <stdio.h>
typedef struct temp {
	int data;
	int (*add)( int );
}Temp;
//
int Temp_add( int i ) {
	return 10 * i;
};
// 메모리 할당 + 함수연결 + 변수 초기값 부여
Temp* new_Temp() {
	Temp* tmp;
	tmp = (Temp*)malloc(sizeof(Temp));
	tmp->add = Temp_add;
	tmp->data = 100;
	return tmp;
}
//
int main() {
	Temp* t;
	t = new_Temp();
//	
	t->data = t->add( 10 );
	printf("%d\n", t->data );	
	free( t );
	return 0;
}

구조체 안에 함수는 선언 불가능하지만 함수포인터는 가능하다.

Temp* t; - 이것은 포인터, 구조체의 실체를 가리키는데, 그 안의 변수는 new_Temp() 함수의 tmp 가 가리키는 공간을 가리키게 되어 값이 대입된다.

void 포인터

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

int* 는 int 형 기억공간을 가리킬 수 있었다.

void* 는 모든 기억장소를 가리킬 수 있는 포인터다.
( 정수형 실수형 구조체 공용체 등 )
단, 해당 기억공간 안에 저장된 내용에 접근할때는 해당 타입으로 캐스팅 해주어야 한다.

#include <stdio.h>
typedef struct temp{
	int data;
	int (*add)(void*, int);
}Temp;
//
int Temp_add(void* self, int i){
	Temp* this;
	this = (Temp*)self;
	return i * 10 + this->data ; 
}
//
Temp* new_Temp() {
	Temp* tmp;
	tmp = (Temp*)malloc(sizeof(Temp));
	tmp->add = Temp_add;
	tmp->data = 100;
	return tmp;
}
//
int main(){
	Temp* t;
	t = new_Temp();    // t = tmp;
//	
	t->data = t->add( t , 20);
	printf("%d\n", t->data );
	free( t );
	return 0;
}

구조체 안에 선언된 모든 함수의 첫번째 매개변수 형태는 void* 로 한다. 구조체 안의 함수포인터로 호출하는 모든 함수는

Temp* this;
this = (Temp*)self;

이 코드를 맨 위부분에 써주도록 한다.

이러면 실제 함수 호출시에
t->add( t, 20 );
t 자기 자신을 매개변수의 첫번째에 넣어주게 된다.

add 입장에서는 자신이 속하여 있는 메모리 공간을 this 가 가리키고 있다. 즉 this 포인터는 자기 자신이 속해있는 구조체를 가리키게 되고, 구조체 안의 변수와 함수에 접근 가능해진다.

#include <stdio.h>
typedef struct temp {
	int data;
	int (*add)( void*, int );
}Temp;
//
int Temp_add( void* self, int i ) {
	Temp* this;
	this = (Temp*)self;
	return i * 10 + this->data;
}
// Constructor 의 역할은 변수의 초기화!!
void Temp_Constructor( void* self, int i ) {
	Temp* this;
	this = (Temp*)self;
	this->data = i;
}
//
Temp* new_Temp( int d ) {
	Temp* tmp;
	tmp = (Temp*)malloc(sizeof(Temp));
	tmp->add = Temp_add;
	Temp_Constructor( tmp, d );
	return tmp;
}
//
int main() {
	Temp* t;
	t = new_Temp( 0 );
	// t->Temp_Constructor( .... ); 
   	// t 라는 포인터를 통해서 호출 불가능
	t->data = t->add( t, 20 );
	printf("%d\n", t->data );
	free( t );
	return 0;
}

Temp_Constructor 는 new_Temp 호출할때 호출된다.
주 용도는 구조체 안의 함수포인터 아닌 변수들의 초기값을 준다.

이것은 포인터를 통해서 호출할 수 없는 함수다.
즉 t->Temp_Constructor( .... ); 이런 식으로 접근은 안된다.


서브루틴

#include <stdio.h>
void add( int i, int j ) {
	//	return;
}
//
int main() {
	add( 10, 20 );
	return 0;
}

리턴타입이 void 로 선언된 함수를 서브루틴 이라고 한다.


Java

Class

class Sample {
	int i = 0;
	int add( int i, int j ) {
		return 100;
	}
}
//
public class Test061 {
	public static void main( String[] args ) {
		System.out.println("HelloWorld");	
	}	
}

class 는 실은 구조체??

  • class 는 이름이 붙는다.
  • class 안에는 변수를 선언할 수 있다! 밖에서는 선언할 수 없다.
  • class 안에서 변수에 대입 연산 등을 수행할 수 없다. 선언만 된다.
  • class 안에서 함수를 선언할 수 있다.
  • class 밖에서는 함수를 선언할 수 없다.
class Temp {
	int data = 100;
	int add( int i ) {
		return i * 10;
	}
}
//
public class Test062 {
	public static void main( String[] args ) {
		Temp t = new Temp();
		t.data = t.add( 20 );
		System.out.println( t.data );
	}	
}

참고로 클래스 이름은 대문자로 시작한다.

new Temp(); 을 먼저 만들어 주어야 한다 : 인스턴스(instance) 라고 부른다.
Temp t = ... , 클래스 이름으로 변수를 선언한다( 참조형변수 ). 인스턴스를 대입한다.

앞서서 선언한 변수 ( 참조형변수 또는 reference 라고 부른다 ) 를 통해 클래스에서 선언된 변수명으로 접근이 가능하다.
참조형 변수를 통해 클래스에서 선언된 함수를 호출할 수 있다.


this

// 위에서 C로 구현한 코드를 java로 옮기는 꼴
class Temp {
	int data = 100;
	int add( int i ) {
		return i * 10 + this.data;
	}
}
//
public class Test067 {
	public static void main( String[] args ) {
		Temp t = new Temp();
		t.data = t.add( 20 );
		System.out.println( t.data );
	}
}

t.add( 20 ); 이것과 같이 호출했을때, 함수 안에서 this 라는 포인터를 쓸 수 있다.

java 의 모든 클래스 안에서 선언된 함수는 내부에서 this 를 쓸 수 있고 , 이것이 가리키는 대상은 호출시에 사용했던 포인터가 가리키는 대상 , 즉 함수가 소속된 인스턴스를 가리키게 된다.

this 를 통해서 data 와 add 함수에 접근할 수 있다.

this 가 가리키는 대상은 어느 참조형 변수를 통해서 호출하느냐에 따라 틀려지게 되고, 이를 통해서 같은 함수의 실체를 호출하더라도 각각 다른 결과를 만들어 낸다.


Constuctor

class Temp {
	Temp( int i ) {
		this.data = i;
	}
	int data = 100;
	int add( int i ) {
		return this.data + i;
	}
}
//
public class Test070 {
	public static void main( String[] args ) {
		Temp t = new Temp( 0 );
		t.data = t.add( 20 );
		System.out.println( t.data );
	}
}

리턴타입 없고 클래스 이름과 같은 함수를 Constuctor ( 생성자함수)라고 한다. 주 역할은 클래스 안에서 선언된 변수의 초기화이고, t.Temp(); 와 같은 형태로 포인터로 호출할 수 없다.

생성자 함수는 참조형 변수 선언시에는 호출되지 않고, 인스턴스가 생성되는 시점에 호출된다.

클래스 안에서 변수를 선언할 수 있고, 함수를 선언할 수 있다.
클래스 안에서 선언된 변수 : 멤버변수 , 프러퍼티 ( property )
클래스 안에서 선언된 함수 : 멤버함수 , 메서드 ( method )

생성자 안에서는 this 라는 포인터를 사용할 수 있고, 이것을 이용해 주로 멤버변수를 초기화 한다.

0개의 댓글