C언어 특이하게 프로그래밍하기

앙마의 이미지

문제 1 : a가 3이면 "a == 3"을 출력하고, a가 3이 아니면 "a != 3"을 출력하라.

방법 1: 줄수를 줄이기
방법 2: printf()함수 호출 줄이기

일반적( 50점 ) :

if( a == 3 ) printf( "a == 3" );
else printf( "a != 3" );

줄 수 줄이기( 75점 ) :

( ( a == 3 ) ? printf( "a == 3" ) : printf( "a != 3" ) ); /* 3항 연산자 사용 */

함수 호출 줄이기( 100점 ) :

printf( ( ( a == 3 ) ? "a == 3" : "a != 3" ) ); /* printf()함수를 한 번만 사용 */

문제 2 : a가 짝수이면, "a는 짝수"을 출력하고, a가 홀수이면, "a는 홀수"를 출력하라. ( 단 printf함수는 한 번만 호출하며 되도록 3항연산자와 %s는 쓰지 말 것. if문 맘껏 쓰십시오. )

점수:

3항 연산자 사용 50점

%s 이용 75점

3항 연산자와 %s안 쓰면 100점

짝수 비교 최적화 +10점

코드 최적화와 관련한 문제이긴 한데... 요즈음은 하드웨어가 워낙 발달하여 저런식의 코드 줄이기가 얼마나 효용성이 있을지는 의문입니다.(제가 아직 현장 경험이 없는지라... 자세한것은 모르겠네요.) 다른 사람의 코드 재사용 측면에서 볼때도 가독성이 떨어져 바람직해 보이지 않구요. 여러분은 어떻게 생각하시나요?

랜덤여신의 이미지

앙마 wrote:
문제 2 : a가 짝수이면, "a는 짝수"을 출력하고, a가 홀수이면, "a는 홀수"를 출력하라. ( 단 printf함수는 한 번만 호출하며 되도록 3항연산자는 쓰지 말 것. if문 맘껏 쓰십시오. )

char *even = "a는 짝수", *odd = "a는 홀수", *str;
if (a % 2) str = odd;
else str = even;
printf("%s", str);

:roll:
장난 좀 쳐봤습니다. :twisted:

앙마의 이미지

인클루드 wrote:
앙마 wrote:
문제 2 : a가 짝수이면, "a는 짝수"을 출력하고, a가 홀수이면, "a는 홀수"를 출력하라. ( 단 printf함수는 한 번만 호출하며 되도록 3항연산자는 쓰지 말 것. if문 맘껏 쓰십시오. )

char *even = "a는 짝수", *odd = "a는 홀수", *str;
if (a % 2) str = odd;
else str = even;
printf("%s", str);

:roll:
장난 좀 쳐봤습니다. :twisted:

점수기준이랍니다. 관건은 %s를 쓰지 말 것 ^^

점수:

3항 연산자 사용 50점

%s 이용 75점

3항 연산자와 %s안 쓰면 100점

짝수 비교 최적화 +10점

autography

인간에게는 자신의 운명을 거부할 권리가 있다.

angpoo의 이미지

  char *dd[] = {"짝","홀"};
  printf("%d는 %s수\n", a, dd[a&1]);
lsj0713의 이미지

문제1.

printf("a %c= 3", (a == 3) * ('=' - '!') + '!');

문제2.

char *str[] = { "a는 짝수", "a는 홀수" };
printf(str[a % 2]);

1번도 2번처럼 풀 수도 있습니다.

그리고 이런건 삽질이라는데 절대적으로 동의 :-)

vacancy의 이미지

저런 식의 함수 호출 줄이기가 무슨 의미가 있는지 모르겠네요.
어차피 if ~ then 이나 마찬가지여서 printf 들 중 하나만 실행될텐데요.
printf 가 여러번 호출될 걸 막는 최적화라면 모르지만 -_-a

codebank의 이미지

코드 최적화라는 취지로 자신만이 알아보는 코드를 만드는 형태는 별로 안좋아합니다.
그 코드를 제가 맡게되면 로직해석보다는 코드해석때문에 많은 시간이 할애되기 때문에... :)

2번째문제는
printf ((a % 2) ? "a는 홀수" : "a는 짝수");
정도가 아닐까요?

------------------------------
좋은 하루 되세요.

dd의 이미지

가독성만 지독하게 떨어질뿐 아니라;
최적화와 '전혀' 관계없습니다.
심심풀이 삼아 하기에는 좋을지 모르겠군요;
(근데 별로 재미없어서-_-)

꼭 확인하고 싶으시다면야
직접 gcc 같은걸로 어셈블리 찍어서 비교해보세요-_-
특히 첫번째 코드와 두번째 코드는 아무런 차이도 없다는;

lazylady의 이미지

구글을 찾아봐도 없는 96s가 뭔가요? :(

건축과 다니면서 프로그램 공부하는 이상한 사람;;

lazylady의 이미지

angpoo wrote:
  char *dd[] = {"짝","홀"};
  printf("%d는 %s수\n", a, dd[a&1]);

흠 angpoo님이 하신 홀짝 알고리즘 멋지군요!

건축과 다니면서 프로그램 공부하는 이상한 사람;;

shgraph의 이미지

Quote:

구글을 찾아봐도 없는 96s가 뭔가요? :(

뚫어지게 보셨으면 구글을 찾는 고생을 안하셨을텐데..T_T;;

96S가 아니라.. %s 입니다..^_^;;;

앙마의 이미지

Quote:

char *str[] = { "a는 짝수", "a는 홀수" };
printf(str[a % 2]);

이것도 특이하다면 특이하네요. 멋져요 :)

autography

인간에게는 자신의 운명을 거부할 권리가 있다.

앙마의 이미지

xeraph wrote:
가독성만 지독하게 떨어질뿐 아니라;
최적화와 '전혀' 관계없습니다.

그런가요? 확인해 봐야 하겠군요.

autography

인간에게는 자신의 운명을 거부할 권리가 있다.

nachnine의 이미지

확인 작업


/*
        .file   "1.c"
        .section        ".rodata"
        .align 8
.LLC0:
        .asciz  "a == 3"
        .align 8
.LLC1:
        .asciz  "a != 3"
        .section        ".text"
        .align 4
        .global main
        .type   main, #function
        .proc   04
main:
.LLFB3:
        !#PROLOGUE# 0
        save    %sp, -120, %sp
.LLCFI0:
        !#PROLOGUE# 1
        mov     3, %g1
        st      %g1, [%fp-20]
        ld      [%fp-20], %g1
        cmp     %g1, 3
        bne     .LL2
        nop
        sethi   %hi(.LLC0), %g1
        or      %g1, %lo(.LLC0), %o0
        call    printf, 0
         nop
        b       .LL3
         nop
.LL2:
        sethi   %hi(.LLC1), %g1
        or      %g1, %lo(.LLC1), %o0
        call    printf, 0
         nop
.LL3:
        mov     0, %g1
        mov     %g1, %i0
        nop
        ret
        restore
.LLFE3:
        .size   main, .-main
        .ident  "GCC: (GNU) 3.3"
*/
#include <stdio.h>

int main (){

int a = 3 ;

if( a == 3 ) printf( "a == 3" ); 
else printf( "a != 3" ); 

return 0 ;

}






/*
        .file   "2.c"
        .section        ".rodata"
        .align 8
.LLC0:
        .asciz  "a == 3"
        .align 8
.LLC1:
        .asciz  "a != 3"
        .section        ".text"
        .align 4
        .global main
        .type   main, #function
        .proc   04
main:
.LLFB3:
        !#PROLOGUE# 0
        save    %sp, -120, %sp
.LLCFI0:
        !#PROLOGUE# 1
        mov     3, %g1
        st      %g1, [%fp-20]
        ld      [%fp-20], %g1
        cmp     %g1, 3
        bne     .LL2
        nop
        sethi   %hi(.LLC0), %g1
        or      %g1, %lo(.LLC0), %o0
        call    printf, 0
         nop
        b       .LL3
         nop
.LL2:
        sethi   %hi(.LLC1), %g1
        or      %g1, %lo(.LLC1), %o0
        call    printf, 0
         nop
.LL3:
        mov     0, %g1
        mov     %g1, %i0
        nop
        ret
        restore
.LLFE3:
        .size   main, .-main
        .ident  "GCC: (GNU) 3.3"
*/
#include <stdio.h>

int main (){

int a = 3 ;

( ( a == 3 ) ? printf( "a == 3" ) : printf( "a != 3" ) ); 

return 0 ;

}





/*
        .file   "3.c"
        .section        ".rodata"
        .align 8
.LLC0:
        .asciz  "a == 3"
        .align 8
.LLC1:
        .asciz  "a != 3"
        .section        ".text"
        .align 4
        .global main
        .type   main, #function
        .proc   04
main:
.LLFB3:
        !#PROLOGUE# 0
        save    %sp, -120, %sp
.LLCFI0:
        !#PROLOGUE# 1
        mov     3, %g1
        st      %g1, [%fp-20]
        ld      [%fp-20], %g1
        cmp     %g1, 3
        bne     .LL2
        nop
        sethi   %hi(.LLC0), %g1
        or      %g1, %lo(.LLC0), %g1
        st      %g1, [%fp-24]
        b       .LL3
         nop
.LL2:
        sethi   %hi(.LLC1), %g1
        or      %g1, %lo(.LLC1), %g1
        st      %g1, [%fp-24]
.LL3:
        ld      [%fp-24], %o0
        call    printf, 0
         nop
        mov     0, %g1
        mov     %g1, %i0
        nop
        ret
        restore
.LLFE3:
        .size   main, .-main
        .ident  "GCC: (GNU) 3.3"
*/
#include <stdio.h>

int main (){

int a = 3 ;

printf( ( ( a == 3 ) ? "a == 3" : "a != 3" ) ); 


return 0 ;

}


앙마의 이미지

요새 컴파일러는 참 똑똑하군요. :)
(원래부터 그런가요? ㅋ)

autography

인간에게는 자신의 운명을 거부할 권리가 있다.

codebank의 이미지

앙마 wrote:
요새 컴파일러는 참 똑똑하군요. :)
(원래부터 그런가요? ㅋ)

gcc의 -S 옵션으로 어셈블리코드를 받아볼 수 있지 않나요? :)
예전부터 있던 옵션인데요.

------------------------------
좋은 하루 되세요.

앙마의 이미지

codebank wrote:
앙마 wrote:
요새 컴파일러는 참 똑똑하군요. :)
(원래부터 그런가요? ㅋ)

gcc의 -S 옵션으로 어셈블리코드를 받아볼 수 있지 않나요? :)
예전부터 있던 옵션인데요.

아... 디스어셈블이 가능하니 똑똑하다는게 아니구요.
C언어 코드가 분명 다른데도 같은 어셈 코드를 보여주니(나름대로 최적화된 어셈 코드인듯) 신기해서 그렇습니다. :)

autography

인간에게는 자신의 운명을 거부할 권리가 있다.

lazylady의 이미지

shgraph wrote:
뚫어지게 보셨으면 구글을 찾는 고생을 안하셨을텐데..T_T;;

96S가 아니라.. %s 입니다..^_^;;;


하하 정말이네요. 아이 쪽팔려-_-

건축과 다니면서 프로그램 공부하는 이상한 사람;;

angpoo의 이미지

shgraph wrote:
Quote:

구글을 찾아봐도 없는 96s가 뭔가요? :(

뚫어지게 보셨으면 구글을 찾는 고생을 안하셨을텐데..T_T;;

96S가 아니라.. %s 입니다..^_^;;;

96s가 갑자기 왜나오나 했었는데 이런뜻이...

오늘의 유머로 추천합니다.

alfalf의 이미지

angpoo wrote:
shgraph wrote:
Quote:

구글을 찾아봐도 없는 96s가 뭔가요? :(

뚫어지게 보셨으면 구글을 찾는 고생을 안하셨을텐데..T_T;;

96S가 아니라.. %s 입니다..^_^;;;

96s가 갑자기 왜나오나 했었는데 이런뜻이...

오늘의 유머로 추천합니다.

제 친구가 얼마전 저에게 그러더군요...

Quote:
(심각하게) 친구야... 이 무한대 기호 세워 놓은게 무슨 뜻이지?

이야기만 듣고 저도 역시 심각하게 생각하다가 깨달은 순간 친구 뒤통수를 한 대 쳐 줬습니다.

이한길의 이미지

angpoo wrote:
shgraph wrote:
Quote:

구글을 찾아봐도 없는 96s가 뭔가요? :(

뚫어지게 보셨으면 구글을 찾는 고생을 안하셨을텐데..T_T;;

96S가 아니라.. %s 입니다..^_^;;;

96s가 갑자기 왜나오나 했었는데 이런뜻이...

오늘의 유머로 추천합니다.

저도 추천합니다... 첨엔 무슨 말인가 하다가...
눈을 좀 흐릿하게 하고 보니까 그래 보이기도 하네요...ㅎㅎ

----
먼저 알게 된 것을 알려주는 것은 즐거운 일이다!
http://hangulee.springnote.com
http://hangulee.egloos.com

전웅의 이미지

앙마 wrote:
문제 2 : a가 짝수이면, "a는 짝수"을 출력하고, a가 홀수이면, "a는 홀수"를 출력하라. ( 단 printf함수는 한 번만 호출하며 되도록 3항연산자와 %s는 쓰지 말 것. if문 맘껏 쓰십시오. )

점수:

3항 연산자 사용 50점

%s 이용 75점

3항 연산자와 %s안 쓰면 100점

짝수 비교 최적화 +10점

코드 최적화와 관련한 문제이긴 한데... 요즈음은 하드웨어가 워낙 발달하여 저런식의 코드 줄이기가 얼마나 효용성이 있을지는 의문입니다.(제가 아직 현장 경험이 없는지라... 자세한것은 모르겠네요.) 다른 사람의 코드 재사용 측면에서 볼때도 가독성이 떨어져 바람직해 보이지 않구요. 여러분은 어떻게 생각하시나요?

코드 최적화와는 관련 없는 문제입니다만, C99 버전으로...

printf(((char *[]){"a는 짝수", "a는 홀수"})[a % 2]);

100점 주세요.. :-)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

졸곰의 이미지

전웅 wrote:
앙마 wrote:
문제 2 : a가 짝수이면, "a는 짝수"을 출력하고, a가 홀수이면, "a는 홀수"를 출력하라. ( 단 printf함수는 한 번만 호출하며 되도록 3항연산자와 %s는 쓰지 말 것. if문 맘껏 쓰십시오. )

점수:

3항 연산자 사용 50점

%s 이용 75점

3항 연산자와 %s안 쓰면 100점

짝수 비교 최적화 +10점

코드 최적화와 관련한 문제이긴 한데... 요즈음은 하드웨어가 워낙 발달하여 저런식의 코드 줄이기가 얼마나 효용성이 있을지는 의문입니다.(제가 아직 현장 경험이 없는지라... 자세한것은 모르겠네요.) 다른 사람의 코드 재사용 측면에서 볼때도 가독성이 떨어져 바람직해 보이지 않구요. 여러분은 어떻게 생각하시나요?

코드 최적화와는 관련 없는 문제입니다만, C99 버전으로...

printf(((char *[]){"a는 짝수", "a는 홀수"})[a % 2]);

100점 주세요.. :-)

a % 2를 a & 1로 바꾸면 더 최적화가 되겠네요. ^^

Running in the 90's
http://spbear.com

전웅의 이미지

spbear wrote:
전웅 wrote:
코드 최적화와는 관련 없는 문제입니다만, C99 버전으로...

printf(((char *[]){"a는 짝수", "a는 홀수"})[a % 2]);

100점 주세요.. :-)

a % 2를 a & 1로 바꾸면 더 최적화가 되겠네요. ^^

최적화가 될지, 아무 영향이 없을지, 오히려 성능을 망칠지는 모르는
일입니다. 앞서 다른 분이 말씀하셨듯이 직접 어셈블리어 코드를
비교하거나 수행 시간 테스트 등을 통해서만 결론을 내릴 수 있는
문제입니다.

사실 이 문제는 코드 최적화라기 보다는 "누가 더 읽기 어려운 프로그램
만드나" 정도의 문제가 되는 것 같습니다.

$ cat tb.c
#include <stdio.h>

unsigned int a = 1;

int main(void)
{
    printf("%d\n", (int)(a & 1));
}

$ cat tr.c
#include <stdio.h>

unsigned int a = 1;

int main(void)
{
    printf("%d\n", (int)(a % 2));
}

$ gcc -S tb.c tr.c
$ diff tb.s tr.s
1c1
<       .file   "tb.c"
---
>       .file   "tr.c"

a 를 signed 형으로 바꾸지 마세요. 똑똑한 gcc 당황합니다. ^^

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

졸곰의 이미지

어셈블리로 바꿨을때 비교해 보고 얘기 드린거였습니다. :)
제 컴파일러에서는 아래와 같은 결과를 내더군요. -ㅅ-
signed와 unsigned에서 차이가 나는 것 같네요.

a%2로 했을때는 아래 코드가

        movl    %edx, %eax
        sarl    $31, %eax
        shrl    $31, %eax
        leal    (%eax,%edx), %eax
        sarl    %eax
        addl    %eax, %eax
        subl    %eax, %edx
        movl    %edx, %eax

a&1로 바꿨을때는

        andl    $1, %eax

이렇게 바뀝니다. :)

전웅 wrote:
spbear wrote:
전웅 wrote:
코드 최적화와는 관련 없는 문제입니다만, C99 버전으로...

printf(((char *[]){"a는 짝수", "a는 홀수"})[a % 2]);

100점 주세요.. :-)

a % 2를 a & 1로 바꾸면 더 최적화가 되겠네요. ^^

최적화가 될지, 아무 영향이 없을지, 오히려 성능을 망칠지는 모르는
일입니다. 앞서 다른 분이 말씀하셨듯이 직접 어셈블리어 코드를
비교하거나 수행 시간 테스트 등을 통해서만 결론을 내릴 수 있는
문제입니다.

사실 이 문제는 코드 최적화라기 보다는 "누가 더 읽기 어려운 프로그램
만드나" 정도의 문제가 되는 것 같습니다.

$ cat tb.c
#include <stdio.h>

unsigned int a = 1;

int main(void)
{
    printf("%d\n", (int)(a & 1));
}

$ cat tr.c
#include <stdio.h>

unsigned int a = 1;

int main(void)
{
    printf("%d\n", (int)(a % 2));
}

$ gcc -S tb.c tr.c
$ diff tb.s tr.s
1c1
<       .file   "tb.c"
---
>       .file   "tr.c"

a 를 signed 형으로 바꾸지 마세요. 똑똑한 gcc 당황합니다. ^^

Running in the 90's
http://spbear.com

전웅의 이미지

spbear wrote:
어셈블리로 바꿨을때 비교해 보고 얘기 드린거였습니다. :)
물론 코드 읽기는 더 어렵다는 것은 인정합니다만.. ^^

a%2로 했을때는 아래 코드가

        movl    %edx, %eax
        sarl    $31, %eax
        shrl    $31, %eax
        leal    (%eax,%edx), %eax
        sarl    %eax
        addl    %eax, %eax
        subl    %eax, %edx
        movl    %edx, %eax

a&1로 바꿨을때는

        andl    $1, %eax

이렇게 바뀝니다. :)

제 글을 다시 한번 읽어주시기 바랍니다 - 특히, 제가 인용한 코드 부분을
확인하시기 바랍니다. 어차피 signed 정수형에 bitwise operator 적용은
프로그램의 이식성을 떨어뜨립니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

졸곰의 이미지

전웅 wrote:

제 글을 다시 한번 읽어주시기 바랍니다 - 특히, 제가 인용한 코드 부분을
확인하시기 바랍니다.

그부분을 늦게 봤네요.. ^^
테스트해보고자하는 마음이 앞서서..
나중에 보고서는 아차 싶어서 확인하고 글 수정하고 나니 뒤에 쓰레드가 달렸네요..^^

Running in the 90's
http://spbear.com

전웅의 이미지

spbear wrote:
그부분을 늦게 봤네요.. ^^
테스트해보고자하는 마음이 앞서서..
나중에 보고서는 아차 싶어서 확인하고 글 수정하고 나니 뒤에 쓰레드가 달렸네요..^^

제 답변이 거의 시..실시간으로 달리고 있군요. 대화 수준입니다. --;

할 일 없이 떠돌고 있는거 너무 티나는군요. (이제부터 바쁜 척 해야지..) --;;;

--
Jun, Woong (woong at gmail.com)
http://www.woong.org