최악의 상황을 가정해보자

 

1. static변수가 Inner class의 인스턴스를 저장하고있다.

2. inner class가 outer class의 context 정보를 가지고 있다.

 

 

해결방법

 

1. static변수에 context를 담지말고 일반변수로 담아라

2. inner class 를 -> static inner class로 변경해라. => static inner class는 hidden으로 outer class instance의 reference를 가지지 않는다.

3. WeakReference를 이용해서 context를 받고 필요할때 get으로 꺼내서 지역변수 수준으로 사용해라.

 

static inner class 생성자 {

   private final WeakReference<Activity> activityRef = new WeakReference<>(activtiy);

}

...

 

public void someMethod() {

  Activtiy activity =  activityRef.get();

 

  if (activtiy != null) {

   ....

  }

 

}

 

 

 

 

 

 

참고

https://android.jlelse.eu/9-ways-to-avoid-memory-leaks-in-android-b6d81648e35e

 

9 ways to avoid memory leaks in Android

I have been an android developer for quite some time now. And I realised that most of that time, I tend to spend on adding new features to…

android.jlelse.eu

 

일단 내가 찾아본 자료들로는 명시적으로 non static inner class의 memory를 해제할 순 없어보인다

무조건 outer class의 instance를 들고있게된다. (hidden으로 들고있게된다고 한다.)

 

 

 의문이 들었던 것은 non static inner class는 무조건 memory leak을 유발시키는 것인가에 대한 고민이었는데

그럴것 같진 않다.

 

GC의 ROOT에서부터 Reach가되는 Object instance가지 탐색을해서 reach하지 않게되면 instacne를 해제하게되는데 

 

아래 그림과 같은 경우는 outer class 및 inner class (non static inner class)의 instance는 사이좋게 GC에 의해 수거가 되게된다.

 

 

하지만 inner class에서 thread가 돌아가면서 긴 시간의 일을 하게되면 어떻게 될까?

 

GC ROOT쪽에서 Outer class instance의 참조를 만약 명시적으로 null 로 준다고 하여도

 

inner class의 Thread가 돌아가게 되고 이는 main process가 inner class instance를 참조하게되고 또한

 

outer class instance역시 참조를 당하기에 memory leak을 유발하게 될 것이다.

 

 

또한 위의 그림과 같은구조인데 static변수가 inner class의 instance를 들고있게되면 역시 위와 같은 

Reference chain이 생기게되어 memory leak이 발생하게 된다.

 

 

 

 

 

참고

https://blog.androidcafe.in/android-memory-leak-part-1-context-85cebdc97ab3

 

Android Memory Leak Part 1: Inner class

Vietnamese Link: https://medium.com/@huynhquangthao/2a487116496f

blog.androidcafe.in

 

 

 

static inner class는 static영역에 처음부터 상주하게 된다. 즉 프로세스가 실행되는 시점부터

이미 메모리에 올라가게된다. 그러므로 static inner class는 outer class의 static변수에는 접근이 가능하다.

 

사실 static inner class는 inner class 라 보기에 어려운 점이 한두가지가 아닌것이 일단 outer class에 대한

reference정보가 없다. 당연한것이 outer class는 static class가 아니고 인스턴스가 생성되기 전이므로

정보가 없게된다. 그러므로 Memory Leak을 관리하기 위한 이점이 있는편이다.

 

다만 static inner class라고 하더라도 outer class의 참조값 혹은 context를 받아와야하는 경우가 생긴다.

그럴때는, WeakRefernce를 사용해서 받아줘야한다.

 

 

 

 

-궁금해서 실험해본내역

static inner class 라고해서 내부의 변수들이 모두 static 변수는 아니다.

명시적으로 static inner class에 static으로 선언한애들만 static 변수가 되는것이다.

static inner class 의 일반변수들도 new로 인하여 인스턴스가 생성될때 할당되며 그때의 인스턴스를통해

맴버변수들에 접근할 수 있게된다. 

 

그러므로 static inner class라고 하더라도 멤버변수들이 outer class의 context같은 참조값을 들고있게된다면

위험한건 마찬가지다. 그러므로 WeakReference 변수로 받아줘야할 필요가 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
public class Main {
    static int c = 20;
    
    
    public static void main(String[] args) {
        
        TestClass tc1 = new TestClass();
        tc1.a = 3;
        
        TestClass tc2 = new TestClass();
        tc2.a = 4;
        
        System.out.println("tc1.a="+tc1.a+"  tc2.a="+tc2.a);
        System.out.println("tc1="+tc1+"  tc2="+tc2);
        
        System.out.println("tc1.b="+tc1.b+"  tc2.b="+tc2.b);
        
        // Main.TestClass.a = 3; //컴파일에러
        System.out.println("static TestClass.c=" + TestClass.c);
 
    }
    
    static class TestClass {
        int a;
        int b = c;
        static int c = 200;
        
    }
    
}
 
 
 

 

 

 

참고

 

https://movefast.tistory.com/41

 

14. Inner Class (Nested Class) and Interface - 중첩 클래스와 중첩 인터페이스

▶ 중첩 클래스 및 중첩 인터페이스를 사용하는 이유 - 자바는 객체 지향 프로그램으로 각 클래스가 관계를 맺으며 상호작용을 한다. 어떤 클래스는 많은 클래스와 상호작용을 하기도 하지만, 다른 어떤 클래스는..

movefast.tistory.com

일반 inner class는 outer class의 인스턴스를 먼저 생성하고나서야 inner class의 인스턴스를 생성할 수 있다.

 

static inner class는, outer class의 이름으로바로 접근하여 인스턴스를 생성할수있다.

 

이점만 봐도 사실 outer와 static inner class간의 메모리 영역은 다른곳에 상주하고있다고 생각을해도 될것같다.

 

 

 

 

SingleTon Class처럼 오래사는 인스턴스에게 가끔 context를 넘겨줘야할 상황이 있을수도있다.

그러나 엄청난 주의가 필요하다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
public class SingletonLeakActivity extends AppCompatActivity {
    
    private SingleTonClass stc;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_static_ref_leak);
 
        stc = SingleTonClass.getInstance(this);
    }
}
 
class SingleTonClass {
    private Context mContext;
    private static SingleTonClass instance;
    private SingleTonClass (Context context) {
        mContext = context;
    }
    static synchronized public SingleTonClass getInstance(Context context) {
        if (instance == null)
            instance = new SingleTonClass(context);
        return instance;
    }
 
}
 
cs

 

위의같은경우라면 SignleTonClass 인스턴스가 SigleTonLeakActivtiy의 context를 계속 쥐고있는 상황이생겨

액티비티가 종료되어도 GC가 수거를 못할수도 있게된다.

 

이럴땐 2가지 솔루션이있다.

1.this대신 getApplicatoinContext()를 넘겨주는것이다. Applicatoin이 살아있는동안의 context이고 액티비티들의 라이프사이클과 관련이없기때문이다.

use the Application context. This context will live as long as your application is alive and does not depend on the activities life cycle. 

결론=> 오래살아야하는 인스턴스중 context가 필요하다면 application-context를 넘겨주는게 좋다.  (activity-context를 넘겨주지마라)

 

 

2.하지만 액티비티의 라이프사이클이 필요해서 this / activity-context 넘겼다면 어떻게해야할까?

명시적으로 null처리를 잘해야한다. 위의예제같은경우는 액티비티(컴포넌트)가 onDestroy될때 싱글톤객체에게 context를 null로 만들도록 명시적으로 처리를 해줘야 할 것이다.

 

 

 

 

참고

https://m.blog.naver.com/PostView.nhn?blogId=rjs5730&logNo=221304797233&categoryNo=0&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

(Android) ActivityContext? ApplicationContext?

안녕하세요. 안드로이드 스튜디오 툴을 해보신 분이면 Context를 한번 쯤 보셨을 거예요. 이렇게 친숙한 ...

blog.naver.com

http://sunphiz.me/wp/archives/tag/applicationcontext

 

applicationcontext – Dog발자

컨텍스트(Context)란? 컨텍스트란 작게는 어플리케이션 자신이 가지고 있는 이미지, 문자열, 레이아웃 같은 리소스 참조를, 크게는 안드로이드 시스템 서비스에 접속하기 위한 관문 역할을 하는 객체다. 이에 대해서는 이미 좋은 글이 있다. 컨텍스트(Context)를 얻는 방법에는 무엇이 있나? 액티비티나 서비스에서 getApplicationContext() 호출 : Application 객체가 Context 형으로 반환된다. 액티비티나 서비스에서 getA

sunphiz.me

https://android-developers.googleblog.com/2009/01/avoiding-memory-leaks.html

 

context에 대한설명과 메모리 leak

 

Avoiding memory leaks

The latest Android and Google Play news and tips for app and game developers.

android-developers.googleblog.com

 

 

안드로이드 Activity 혹은, View들을 Static변수에 담는건 피하는게 좋다.

 

Java Life Cycle과 Android의 Component Life Cycle이 조금 차이가있기에 설명해보고자한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
 
public class StaticRefLeakActivity extends AppCompatActivity {
 
    static Activity leakActivity;
    static TextView leakText;
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_static_ref_leak);
 
        leakActivity = this;
        leakText = new TextView(this);
    }
 
}
 
 

 

위와 같은 코드가 있을때 메모리 참고는 아래그림처럼 된다.

static변수들은 process가 시작할때 초기화되고 static영역에 자리잡게된다. 클래스의 인스턴스와는 전혀 다른

메모리공간에 상주한다고 봐도된다.

 

그런데 위의 코드에서 Activity가 종료된다고 생각해보자.(다른화면으로의 전환) Activitiy가 종료된다는것은 안드로이드 컴포넌트의 수명주기가 종료되었다는것이다. 하지만 객체의 수명은 이제 GC에의해 참조되는것이 없으면 끝나게된다. 

 

하지만...static영역은 프로세스(앱의실행)가 끝나지 않았기에 아직 StaticRefLeakActivtiy를 참조하고있고 또한, 익명의 TextView 인스턴스 역시 참조당하고 있다. TextView인스턴스 역시 this(StaticRefLeakActivtiy의 인스턴스)를 참조하고있기에 문제가되는상황이다. (GC가 수거를못해감)

 

그렇기에 static에 뷰 혹은 액티비티 인스턴스를 담는것은 매우 위험하다. 

만약 정말 그래야하는 상황? 이 생긴다면 해제를 정말 기가막히게 잘해줘야할 것이다.

 

 

 

참고

 

https://medium.com/@zhangqichuan/memory-leak-in-android-4a6a7e8d7780

 

Memory leak in Android

If Java is your first programming language, most likely you will take memory management for granted and let the built-in JVM Garbage…

medium.com

 


날짜와 시간 출력

$ date



로그인된 사용자 확인

$ who



로그인된 나자신 보는 법

$ who am i



문자 출력: echo



$ echo thi is a test

$ echo

$ echo one      two              three

->one two three // 단어 사이 추가공백 줄여준다.




>파일작업

디렉터리 저장된 파일 확인

$ ls  


파일 내용출력

$ cat


파일 단어 수 계산. 파일에 포함된 라인수, 단어수, 문자 수

$ wc filename


$ wc -l    //line 라인수

$ wc -c //문자수

$ wc -w //단어수



파일복사

$ cp names saved_filenames



파일이름변경

$ mv primaryfiles changedfilename



파일삭제

$ rm removefilename



>파일 디렉토리

/ = root directory를 칭함.


작업 Directory 출력

$ pwd



디렉토리 변경

$ cd documents  // 디렉토리 변경



$ cd .. 한단계 위 디렉토리로 감.



$ cd ../.. 2단계 위로



$ ls directoryname 해당 디렉토리 목록을 얻을 수있음

$ ls dir/name/blabal  이런거 역시 가능.



l(문자) 특정 디렉터리 파일에 대해 좀더 상세하 ㄴ설명 제공한다.



$ ls -l



특정 파일을 다른 디렉토리로 복사

$ cp pro/we to/destin



혹은

$ cp pro/we to/we  // 두파일이 서로 다른 디렉터리에 있기에 가능 



혹은 아래처럼 복사되는 파일명을 생략하면 자동으로됨

$ cp pro/we foldername



디렉터리 간 파일이동

$ mv memos/my pro/plan



혹은 이름 안바꾸면서 그대로 이동하려면 폴더이름만 적어주면 자동으로됨

$  mv memo/plan dest



파일 링크: ln 커맨드

$  ln from to

해당 링크는 from 파일을 to 파일로 링크한다.    //(from - 현재존재하는, to- 새로 이름지을 )



$ ln wb wobo

파일 wb를 wobo이름으로 링크.



ls하면

wb, wobo 가 들린다.



$ ls -l 을하면 2번째열에 링크수가 표시된다.

링크중 하나만 삭제하면 다른 한놈의 링크수는 1로 변하게된다.



$ ln /users/jh/wb .  이런식으로도 가능하다.



심볼릭 링크

$  ln -s from to    

심볼릭 링크는 원본 파일을 가리킨다.


ls결과 첫번째 무자로, l이 나오면 심볼릭 링크이다.


$ ls -Ll   심볼릭 링크가 가리키는 파일에대한 정보 목록을 가져올 수 있다.


심볼릭 링크가 가리키는 파일을 삭제하면, 심볼릭 링크는 무효화되지만, 삭제되지는 않는다.



디렉터리 삭제:rmdir 커맨드


$ rimdir /bla/blaaa


비어있지않다면 성공한다.


모든파일을 지우려면


$ rm -r dir


$ rm -rf dir  삭제작업 강제로 빠르게 진행됨.



*

별표

패턴 *, 와일드 카드 개념으로 사용된다.

*t1


chap*


? 는 한문자

?? 는 두문자 아무거나의 개념으로 사용된다.


$ echo ?

a b c

$ echo a?

aa

$  echo ??

aa bb cc

$  echo ??*  (2문자이면서 그이사 ㅇ아무거나 모두 출력)

aa aax alice bb cc report1 report2 report3



단일 문자를 일치시키는 방법.

[0-9] 0qnxj 9Rkwl dlfcl.

[f-z] f부터 z까지

[a-np-z]* a에서 n또는, p부터 z까지 문자로 시작하는 모든파일


[ 다음에 오는 첫번째 문자가 !와 일치하면 반전된다. 즉, 대괄호 안에 있는 문자를 제외한 모든 문자가 일치

[!a-z] 소문자를 제외한 모든 문자


*[!o] 소문자 o로 끝나지 않는 모든 파일과 일치시킨다.


echo a* a로시작하는 파일 이름 출력

cat *.c .c로 끝나느 모든 파일 출력

ls x* x로 시작하는 모든 파일이름 출력

rm * 모드 지우기

echo a*b a로시작하고, b로 끝나느 모든 파일 이름 출력

ls [a-z]*[!0-9] 소문자로 시작하고, 숫자로 끝나지 않는 파일을 출력.


 들여쓰기 재정렬

{visual block}= 

 탭 대신 공백쓰기 

set et, retab 

 단어 완성 

Ctrl-N, Ctrl-P 


=G

G는 재정렬할 범위, %, }}, ]] 사용가능합니다.


=100G라고 입력하면 현재행부터 100번째행가지 들여쓰기 재정렬가능.



또한 Ctrl-N 혹은 Ctrl- P를 누르면 이전에 나왔던 단어들을 완성시켜주는 기능입니다.

입력모드에서(insert, i키눌렀을때 ) 동작하는거이므로, 작성중 모드를 바꿀 필요가 없습니다.




더하기 낱말모드

이메일같은거는 @나 . 같은걸로 구분이 되어있어서 아이디부분까지 짤릴 수 있습니다.


jh21@sam.com 이런경우에


jh21만 완성될수있습니다 .그럴때는


CTRL-X , CTRL-N 을 누르면 완성됩니다. sam까지만 입력되고 또, .com 입력하려면, ctrl-X ctrl-N 누르면 완성되게 됩니다.


단어나 특별한 경계로 움직이기

 0

0번째 열 

공백을 제외한 행의 시작 부분 

 $

마지막 열(행의끝) 

단어의 시작 위치 혹은 문장부호의 경계를 따라서 이동 

w와 같으나 단어의 끝부분에 위치 

w와 비슷하나 진행방향이 역방향. 

 

 



괄호나 문단, 블록단위 이동

가장 가까운 괄호 짝으로 이동 (짝이맞는걸로 이동) 

(, ) 

문장 단위의 시작위치, 끝 위치로 이동 

{, } 

문단 단위의 시작위치, 끝 위치로 이동 

[[, ]]  

블록 단위의 시작위치, 끝위치로 이동 




삭제 명령의 다양한 실행모드

d$ 

현재커서위치부터 행 끝까지 삭제 

dd 

형재행을 삭제 

dj 

현재행과 아래행 삭제 

dk  

현재행과 위행 삭제 

dw 

현재커서위치부터 단어 끝까지 삭제 

de 

 

d^ 

현재커서위치부터 행시작 부분까지 삭제 

d} 

현재 커서위치부터 문단 끝까지 삭제 



{motion} => 단어 사이나 행, 특정 위치로 이동하는 키입력을 가리킴.


{motion}을 사용하는 명령의 예

 y{motion}

{motion}만큼 복사 

d{motion} 

{motion}만큼삭제 

c{motion} 

{motion}만큼 변경 






 

Nerd tree는 vim 유저들중 사랑받는 플러그인 중 하나입니다.

http://www.vim.org 에 접속합니다.

왼쪽의 Scripts를 누르고 keywords에 nerd를 입력하여 검색된 결과를 살펴 봅니다.


눌러서 다운을 받습니다. 


리눅스에서는 ~/.vim 디렉토리에 다운받아 압축을 풀어주면 됩니다.

$ cp ./NERD_tree.zip ~/.vim

$ cd ~/.vim

$ unzip ./NERD_tree.zip


그다음 VIM을 열어서

:NERD 까지입력하고 tab을 치면 :NERDTree가 자동완성되어 입력되는것을 확인하실 수 있습니다.






NERD tree 명령어

:NERDTree [path] 

디렉터리를 열어서 보여줍니다. 

path를 생략하면 현재 디렉터리를 열어줍니다.

:NERDTreeClose 

NERD tree 창을 닫습니다.

:NERDTreeFind 

현재 열고있는 파일이 트리의 어디에 있는지 보여줍니다.




NERD tree의 주요 브라우징 단축키

 enter, o

 디렉토리의 경우이동, 파일인 경우 열어줍니다. 열려있는 노드인 경우 닫습니다. 

 t

 파일을 새로운 탭에 열어줍니다. 

 T 

 파일을 새로운 탭에 백그라운드로 열어줍니다. 

 x 

 현재 선택된 노드를 닫고 상위 노드로 이동합니다. 

 X 

 현재 선택된 노드를 포함하여 하위 노드를 모두 닫습니다. 

 e 

 선택된 노드를 새 창에서 열어줍니다. 





TagList

소스코드를 분석하여, 변수, 매크로, 함수의 목록을 만들어 줍니다.

예를 들어 현재 디렉터리에있는 *.c 파일을 분석하려면 다음 명령대로 입력하면 됩니다.


:TlistAddFiles *.c   //*.c 파일을 읽어들이라는 명령

:TlistToggle         // 태그창을 열거나 닫는 명령.


각 태그에서 엔터를 치면 즉시 해당 태그로 이동하여 편집할 수 있고, 태그에서 스페이스바를 누르면 변수나 함수의 선언 부분을 볼 수도 있습니다.



taglist도 역시 vim 사이트에서 받습니다.


$ cp ./taglist_46.zip ~/.vim

$ cd ~/.vim

$ unzip ./taglist_46.zip



taglist와 Nerd Tree를 같이 뛰웠습니다.





VIM Mouse

=> 터미널 창에 마우스 (mouse) 클릭이 가능하도록 설정


:set mouse=a 


매번 귀찮으니깐, 


$ vim ~/.vimrc  에 set mouse=a 등록할 것~!





ctag와 cscope는 해당 pdf를 참고하여 설치및 사용해보았습니다.


csl.skku.edu/uploads/SSE3044F12/vim_ctags_cscope.pdf



ctags 설치

-> 소스코드 함수, 구조체 등 태그 리스트 출력.


*설치

$ sudo apt-get install ctags


*태그 생성방법.

$ ctags [options] [files] 명령이용하여 생성.

$ ctags -R  //-R의 경우, 특정디렉토리 아래에있는 소스파일들에 대해 태그 생성.



태그 생성됨. 그 이후 이런식으로 치면 검색됨.

$ vim -t main 



 vim 상에서 검색을 하고싶다면

:ta tag이름 으로 치면 검색된다.



다음 태그로 이동할때는 :tn   이전은 :tp 로 이동.


tj 명령이용하면 키워드 일치하는 태그가 한개일 경우 바로이동, 두개이상일 경우 목록을 출력하고 그 중 선택하여 이동


:tj tagname 하면 여러개가 나오고 그때 번호를 눌러서 이동가능.









cscope

ctags는 변수, 함수, 매크로, 구조체는 검색되는데 함수 호출한 부분,함수에 의해 호출되는 부분들은 검색이 안됨.


반면 cscope는 변수, 함수, 매크로, 구조체, 전역선언, 특정함수에 의해 호출되는 함수, 특정 함수를 호출하는 함수, 문자열 등을 검색할 수 있다.


$ sudo apt-get install cscope







cscope database 생성방법


http://manime.tistory.com/entry/cscope-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%AC     참고.


$  find . \( -name '*.c' -o -name '*.h' -o -name '*.s' -o -name '*.S' \) -print > cscope.files



db 파일인 cscope.files 가 생성됨.


이걸 vim에서 검색할 수 있도록 ~/.vimrc 에등록 하거나


아래와 같이 vim에 서 등록하기도 가능.


 :cs add ~/경로명~~~/cscope.out



아래 site가 설명이 정말 잘되어있습니다. 

http://blog.naver.com/PostView.nhn?blogId=rullrow&logNo=70169937319





: cs find s myfunc 로 검색가능.


검색할 태그번호를 선택하고 엔터를 치면 해당 태그로 이동.

다음검색어는 :cn , 이전은 :cp 로 이동가능.













'리눅스 Linux > VIM VI Editor' 카테고리의 다른 글

VIM 개발자에게 유용한 기능들  (0) 2018.04.12
VIM 편리한 편집기술  (0) 2018.04.12
vim 파일 관련 편집 기능  (0) 2018.03.27
vim 문자열 관련 기능  (0) 2018.03.26
VIM 옵션, 도움말, 에러처리  (0) 2018.03.23

C언어 타입선언


C언어를 공부하며 코딩한지는 오래됐지만 생각보다 C언어 타입 선언의 읽기와 이해는 맨날 볼때마다 헷갈릴때가 있습니다. 


그래서 이번에 확실하게 정리하기 위해 포스팅을 해봅니다.



C언어의 타입선언 읽기 RULE


- 이름부터 무조건 읽어라. 그리고 이름 에서 가까운 순서로 읽으면 된다.


- 우선순위가 가장 높은것은 [] 배열연산자와, 함수연산자 ()는 먼저 읽어라.


ex:)


int *  (* myVar) [100];

 5 4   2     1       3


해석

=>myVar는 주소를 담는 포인터변수이며, 배열크기 [100]을 가르킬수있는애이며, 배열의 원소는 포인터 변수인데 int형인 자료를 가르키는 애로 쓰인다.


즉 그림으로 그려보면



자 한번에 너무 확 달린것같나요?

그럼 차근차근해보겠습니다. 


char (*arr1)[4]; 

==> arr1은 포인터변수로서 주소를 가지는데, 이변수는 배열의 크기가 [4]인애를 가르키고 그 배열은 char형 자료들로 채워져있다!


-> arr1은 2차원배열의 형태를 가질 수 있습니다.

arr1[임의의 크기][4]



비교) 

int *whoA[4];  // 포인터 배열.


whoA는 크기가 [4]인 배열인데, 포인터변수를(주소를) 가지고있으며, 그 주소는 int형을 가르킨다.



타입 선언 Reading skill


*

- 지금까지 읽은것의 타입은 주소(포인터변수)

- 앞으로 읽을것(다음에 나오는것은) 은, 그 주소(포인터변수)가 가리키는 대상의 자료형(타입)


[]

- 지금까지 읽은 것은 배열

- 앞으로 읽은 것은 배열의 원소하나의 자료형(타입)


()

-지금까지 읽은것은 함수이며 ()안에는 함수파라메터(이건 개발자가 구분해야됨)

- 앞으로 읽을것(다음에 나오는것은) 함수의 리턴타입.





char * (*test1) [10]

5     4 2 1       3


변수명은 test1이며, 자료형은 포인터이며, 그 포인터는 배열크기가 [10]인것을 가리키는데, 그배열은 원소는 포인터 변수인데, 그 포인터 변수는 char 자료형을 가리킨다.





int (* test2 [5] ) (int)

 5  3   1      2    4 


변수명은 test2이며, [5] 배열로써, 원소는 포인터변수인데 이포인터 변수가 가리키는 것은, 파라메터가 (int) 1개를가지며, 반환형이 int인 함수이다.



// 2의 경우 파라메터 변수를 생략할 수 있다. (*blabla)[10]...

char ( * myfunc ( char (*)[10]) ) [10];

5      3    1           2                4


이름이 myfunc이며, 파라메터로 2차원 배열을 가지며, 반환형은 포인터변수인데 이포인터 변수는, 배열의 크기가 [10]인것을 가르키며, 그배열은 char를 담고있다.












+ Recent posts