$bash

C/C++ string in switch/case

0x0300 : Study/0x0304 : Programming

요새 CTF를 하면서 C든 뭐든 프로그래밍 너무 못한다 생각이 너무나도 들어서 다시 공부하고 있다.

그때마다 생각나는거 생각을 써야겠다.


1
2
3
4
5
6
7
8
9
10
switch(string)
{
case "Name":
...
break;
case "Age":
...
break;
}
 
cs


위 구문은 switch 문을 그냥 의식의 흐름(?) 대로 string을 해봤는데...

switch의 controlling expression을 정수 형 대신 문자열를 사용 할 수 없기에 위 구문은 당연히 될 수가 없다.


switch 명령은 case가 많을수록 이론상으로 if문과 성능 차이가 기하급수로 벌어지게 되어 있다. 왜 그럴까?

if - else if 열거식의 경우엔 비교하는 대상 중 어느 한쪽이 상수라면 자동으로 점핑 테이블을 만들어 마치 switch - case처럼 동작하기 때문이다. 좀 더 자세히 생각해 보면, 상수 값에 따라 IP(Instruction Pointer) 는 함수호출처럼 자신의 주소를 향해 뛰어간다. break 구문을 만나면 switch 가 끝나는 블럭으로 또 한 번 점프한다. break 나 continue 는 goto 구문의 다른 (특수한 용도로 한정된) 이름이다. 그런데 상수가 아닐 경우는 점핑 테이블 생성이 불가능해진다. 결과적으로 속도에서 차이가 날 수 밖에 없다는 것이다. jmp table을 쓰는 것은 시간이 오래 걸리는 테이블 생성 작업을 1회 한 후 한 번의 비교로 원하는 곳으로 찾아가 작업하겠다는 성능을 기대하는 것인데 변수가 case에 들어가게 되면 일반적인 if - else if 로밖에 구현이 안되는 것이다.


EIP = EIP + jmptable[Index]; 

// 이게 맞는건지는 나도 잘 모르겠따리...


많은 case를 string을 넣어 사용한다면 결론적으로 많은 jmp table 요구한다. 게다가 변수가 상수가 아닐 경우에는 Index 값 자체가 산출되지 않아 저런 식으로는 불가능하고 연결리스트 따위를 동원해야하니 속도 성능 같은 건 기대도 못 할지도 모른다.


1
2
3
4
5
6
7
if(strcmp(string"Name"== 0)
{
}
else if(strcmp(string"Age"== 0)
{
}
else ...
cs


if를 써서 strcmp 를 사용하여 위의 switch 구문을 표현 할 수 있다. 사실 그냥 내가 case 써서 string으로 구현하고 싶은 맘이다.

사실2 더 큰 문제는 else if 중첩에는 한계가 있다는 것이다. (error code C106 참고)


C++ 로 먼저 좀 생각해보자. jmptable 을 요구하여 한다면, STL 를 사용하여 테이블을 생성하여 점프를 한다면 충분히 가능하지 않을까 생각이 든다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static map< stringint > m;
void Init(){
    m["Name"= ENUM_NAME;
    m["Age"= ENUM_AGE;
}
 
void func(){
    switch(m[string]){
        case ENUM_NAME:
            ...
            break;
        case ENUM_AGE:
            ...
            break;
        }
}
cs


map를 사용하여 switch 구문에 대한 문자열 문제는 해결된다. 어느정도 많은 case 문이 나와도 깔끔하게 정리가 될 수 있고, map가 어느정도 성능을 개선 해 주기 때문에 좋다고 생각한다. 하지만 정말로 괜찮을까?


초기화 함수 하나 만들고 변수 하나 선언하고 열거형을 만들면 된다. 하지만 이런 작업을 하고 있으면 굉장한 손해를 본다. 성능상으로야 가장 좋지만(map 대신 hash_map을 쓴다면, 비록 표준은 아니지만 성능으로는 좋은 성과를 볼 수 있다.) 코드의 유지보수 관리에는 그켬을 초래할 수 있다.


머 중요한 사실은 cpp을 하는 것은 아니고 내가...이러한 문제는 따로 STL map에 따로 case token 을 선언해준다면 충분히 해결 될 것이라고 생각한다.


어디까지나 cpp 조빱이 생각한거라... 나도 올바른 정답은 아니다. 또 원래 C를 공부 하고 있어서 C에 대해서도 찾아봤다.


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
33
#define BADKEY -1
#define A1 1
#define A2 2
#define B1 3
#define B2 4
 
typedef struct { char *key; int val; } t_symstruct;
 
static t_symstruct lookuptable[] = {
    { "A1", A1 }, { "A2", A2 }, { "B1", B1 }, { "B2", B2 }
};
 
#define NKEYS (sizeof(lookuptable)/sizeof(t_symstruct))
 
int keyfromstring(char *key)
{
    int i;
    for (i=0; i < NKEYS; i++) {
        t_symstruct *sym = lookuptable + i*sizeof(t_symstruct);
        if (strcmp(sym->key, key) == 0)
            return sym->val;
    }
    return BADKEY;
}
 
/* ... */
switch (keyfromstring(somestring)) {
case A1: /* ... */ break;
case A2: /* ... */ break;
case B1: /* ... */ break;
case B2: /* ... */ break;
case BADKEY: /* handle failed lookup */
}
cs


stack overflow에서 나온 자료인데...그냥 if 쓰는게 더 나을꺼 같따...

위 소스에 대해서는 해당 링크를 참고 하면된다.


링크 :: https://stackoverflow.com/questions/4014827/best-way-to-switch-on-a-string-in-c

'0x0300 : Study > 0x0304 : Programming' 카테고리의 다른 글

C/C++ 제곱근 SQRT  (0) 2017.10.19
C/C++ int main, void main  (0) 2017.10.18
C/C++ string in switch/case  (0) 2017.10.18
NASM - LD 컴파일 후 실행  (0) 2017.05.13
GDG DevFest 요약?  (0) 2016.12.20
C - 배열과 포인터  (0) 2016.06.14

How to Create a Programming Language

0x0300 : Study/0x0306 : ETC

How to Create a Programming Language?


1. Become familiar with terminology.

Compiler writers often use unfamiliar terminology. Read up on compilers before proceeding. Be sure to know everything that you need to know.


2. Decide what problem your language is solving.

Is it addressing a domain-specific problem, or is it a general purpose language?


3. Think about the semantics of your language and the concepts of it.

- Are you going to allow direct pointer access or not?

- What are the data types of your language?

- Is it a static or dynamic language?

- What is your memory model? Are you going to use a garbage collector or manual memory management? (If you use a garbage collector, prepare to write one or adapt an existing one to your language.)

- How are going to handle concurrency? Are you going to use a simple threading/locking model or something more complex like - Linda or the actor model? (Since nowadays computers have multiple cores.)

- Are there primitive functions embedded in the language or will everything come from a library?

- What is the paradigm or paradigms of you language? Functional? Object-oriented? Prototype (like JavaScript)? Aspect-oriented? - Template oriented? Or something entirely new?

- How is your language going to interface with existing libraries and languages (mainly C)? This point is important if you're building a domain-specific language.

- Finally, some of the answers to this questions are going to be answered by the second step and will help you answer the next step.


4. Think of some specific tasks that someone would want to be able to perform with your language.

For example, 'they may want to direct a robot to follow a line' or 'they may want to create relatively portable desktop programs in it' or 'they may want to create web applications with it'.


5. Experiment with syntax ideas (the text of the language) for the above examples.

Be careful to keep your language in the context-free language category or something inside it. Your parser generator and you will appreciate it later on.


6. Write out a formal grammar for the syntax.


7. Decide whether the language will be interpreted or compiled.

Meaning that in the interpreted world your user will typically edit your program in an editor, and run it directly on the interpreter; while in the compile world, your user will edit your program, compile it, save the resulting executable somewhere and run it.


8. Write the front end scanner and parser or find a tool that helps you with this.

Also, think about how your compiler/interpreter will warn your user about erroneous programs and syntax errors.


9. Use the parser information to write the object code or an intermediate representation.

Have the parser create an AST, then create your object code from the AST using three address code or its big brother SSA, then create a symbol table to define your functions, global variables, etc.


10. Write the executor or code generator that will bind everything together.


11. Write many test programs to test the language.

You want to create programs that stress the burdens of your formal grammar in order to see that your compiler accepts everything that is inside your definition and rejects everything that is outside of it.


12. Consider how the user will debug their own programs.


13. If your language uses a standard library, you will want to write it.

Specifically, if you write a compiler, you will need the code that the operating system will execute in order to begin running the user code (for example, allocating all global variables).


14. Publish your language, along with the specification for it and some examples of what you can do in it.

Don't forget to document how you can integrate with existing libraries, languages and how to use the runtime features and/or standard library.


'0x0300 : Study > 0x0306 : ETC' 카테고리의 다른 글

How to Create a Programming Language  (0) 2017.09.07
여기는 왜 안되는거죠....???  (0) 2016.09.08
8. 저작 재산권  (1) 2016.07.03
7. 저작권  (0) 2016.07.03
6. 정보기기 보안 및 관리 수칙  (0) 2016.06.30
5. 해커의 분류  (0) 2016.06.30

GDG campus summer party

0x0100 : 놀고싶다
GDG campus summer party 자료 입니다!
사실 볼건 없지만,,,발표 끝나고 올려달라고 부탁하시는 분들이 많아서 따로 올리게 되었습니당! 별거없는 자료 이지만 발표하게 해주신 GDG에게 감사 드리고 대회 때매 하루 참석 못하게 됬는데 스태프 주제에(?) 그점 죄송하다고 말씀드리고 좋은 하루되세요 :D



'0x0100 : 놀고싶다' 카테고리의 다른 글

GDG campus summer party  (0) 2017.08.22
15th 해킹캠프 - 후기  (0) 2017.02.22
GDG DevFest 2016  (0) 2016.11.07
WITHCON 선포식 후기  (0) 2016.11.07
DEVIEW2016 컨퍼런스  (0) 2016.10.26
WhiteHat CTF  (0) 2016.10.09