게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
아래 "error C2440 질문입니다." 예제 정상입니다. 안틀렸어요.
게시물ID : programmer_16455짧은주소 복사하기
작성자 : nsys
추천 : 3
조회수 : 2423회
댓글수 : 25개
등록시간 : 2016/03/31 23:16:06
옵션
  • 본인삭제금지
  • 외부펌금지
http://www.todayhumor.co.kr/board/view.php?table=programmer&no=16432&s_no=16432&page=1

코드가 잘못됐다 하시는분 있는데 절대 아닙니다.

[root@archlinux ~]# cat test.c
#include <stdio.h>

int main(int argc, char **argv) {
        char *p = &"ABCD";

        printf("%x \n", p);
        printf("%x \n", p+1);
        printf("%x \n", p+2);
        printf("%x \n", p+3);
        printf("%x \n", p+4);
        printf("------------\n");

        printf("%x %x \n", &"ABCD", p);

        return 0;
}

흔해빠진 포인터 예제군요.

&"ABCD"가 틀렸다고 하신분. 틀렸다고 하신게 틀렸습니다.

"ABCD"는 컴파일 타임에 rodata 로 넘어가고 임시 심볼로 대체 됩니다. 그러므로 정당한 문법입니다.

[root@archlinux ~]# gcc test.c -S
test.c: In function ‘main’:
test.c:4:12: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
  char *p = &"ABCD";
[root@archlinux ~]# cat test.s
        .file   "test.c"
        .section        .rodata
.LC0:
        .string "ABCD"
.LC1:
        .string "%x \n"
.LC2:
        .string "------------"
.LC3:
        .string "%x %x \n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $32, %rsp
        movl    %edi, -20(%rbp)
        movq    %rsi, -32(%rbp)
        movq    $.LC0, -8(%rbp)
        movq    -8(%rbp), %rax
        movq    %rax, %rsi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        movq    -8(%rbp), %rax
        addq    $1, %rax
        movq    %rax, %rsi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        movq    -8(%rbp), %rax
        addq    $2, %rax
        movq    %rax, %rsi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        movq    -8(%rbp), %rax
        addq    $3, %rax
        movq    %rax, %rsi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        movq    -8(%rbp), %rax
        addq    $4, %rax
        movq    %rax, %rsi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        movl    $.LC2, %edi
        call    puts
        movq    -8(%rbp), %rax
        movq    %rax, %rdx
        movl    $.LC0, %esi
        movl    $.LC3, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 5.3.0"
        .section        .note.GNU-stack,"",@progbits

대충 패턴 보이죠? C 코드에서 포인터 참조 한 것과, +1 +2 +3 한 부분입니다.

[root@archlinux ~]# gcc test.c -c
test.c: In function ‘main’:
test.c:4:12: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
  char *p = &"ABCD";
            ^
[root@archlinux ~]# objdump test.o  -D

test.o:     file format elf64-x86-64

생략

Disassembly of section .rodata:

0000000000000000 <.rodata>:
   0:   41                      rex.B
   1:   42                      rex.X
   2:   43                      rex.XB
   3:   44 00 25 78 20 0a 00    add    %r12b,0xa2078(%rip)        # a2082 <main+0xa2082>
   a:   2d 2d 2d 2d 2d          sub    $0x2d2d2d2d,%eax
   f:   2d 2d 2d 2d 2d          sub    $0x2d2d2d2d,%eax
  14:   2d 2d 00 25 78          sub    $0x7825002d,%eax
  19:   20 25 78 20 0a 00       and    %ah,0xa2078(%rip)        # a2097 <main+0xa2097>

링크 하기 전이라, 00으로 시작하는군요. 

그렇다면 링크까지 한다면?

[root@archlinux ~]# gcc test.c
test.c: In function ‘main’:
test.c:4:12: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
  char *p = &"ABCD";
            ^
[root@archlinux ~]# objdump a.out -D

a.out:     file format elf64-x86-64

생략

Disassembly of section .rodata:

0000000000400680 <_IO_stdin_used>:
  400680:       01 00                   add    %eax,(%rax)
  400682:       02 00                   add    (%rax),%al
  400684:       41                      rex.B
  400685:       42                      rex.X
  400686:       43                      rex.XB
  400687:       44 00 25 78 20 0a 00    add    %r12b,0xa2078(%rip)        # 4a2706 <__FRAME_END__+0xa1f3e>
  40068e:       2d 2d 2d 2d 2d          sub    $0x2d2d2d2d,%eax
  400693:       2d 2d 2d 2d 2d          sub    $0x2d2d2d2d,%eax
  400698:       2d 2d 00 25 78          sub    $0x7825002d,%eax
  40069d:       20 25 78 20 0a 00       and    %ah,0xa2078(%rip)        # 4a271b <__FRAME_END__+0xa1f53>

400684 에서 시작 하는군요.

실행 결과 볼까요?

[root@archlinux ~]# ./a.out
400684
400685
400686
400687
400688
------------
400684 400684


네. 예제 자체는 문제도 없었고 의도는 다음과 같습니다.

1. 문자열 상수는 어디에 저장될까? 찍어보자.
2. 
        char *p = &"ABCD";
        printf("%x %x \n", &"ABCD", p);
두가지 "ABCD"는 같은가? 찍어보자.


이런 정상적인 예제를 왜 printf 로 A 찍고 B 찍고 C 찍는다고 마음대로 수정해서 설명하고 있는지 모르겠네요.

이런 예제는 빌드해서 돌리는데 몇십분씩 안걸립니다. 

틀렸다고 주장하기 전에 한번이라도 빌드 돌리고 이야기 하시면 좋겠군요.
전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호