포인터에 대한 질문

익명 사용자의 이미지

포인터의 개념에 대해 공부하다 궁금한 점이 있어서 질문드립니다. 일단 소스를 보시죠~
main()
{
int *p1, *p2, value1=1, value2=3;
p1=&value1, p2=&value2;
printf("*p1 address = %p\t *p2 address = %p\n", &p1, &p2);
printf("p1 has address = %p\t p2 has address = %p\n", p1, p2);
printf("*p1 point = %d\t *p2 point = %d\n", *p1, *p2);
printf("value1 address = %p\t value2 address = %p\n", &value1, &value2);
printf("p1-p2=%d\n",p1-p2); <--- 이 값은 도대체 무엇을 뜻하는 것입니까?
}

익명 사용자의 이미지

단순히 p1, p2 라고만 쓰게 되면 p1, p2 각각의 주소값을 가지게 됩니다.
그러니 p1-p2를 하게 되면 p1과 p2의 주소값의 차이가 나오겠죠?
하지만 p1이 먼저 선언되어 있기 때문에 p2는 p1보다 4가 큰 값일 것입니다.
(모든 포인터는 4Byte를 차지하기 때문에.. 물론 아주아주 옛날꺼에선 2byte겠
죠? ^^;;)
그럼 결과는 -4가 나올텐데.. 좀 이상하네요.. 보통은 그런걸 구해볼땐 p2-p1
을 하든데.. ^^;
뭐 취향차이려니 하지죠..
어쨌건 원하는것은 두 포인터들 사이의 주소 간격을 구해보는 것일 것입니다.

뭐.. 도움이 되셨는지 모르겠네요.
허접한 플그래머의 허접한 답변 이었습니다.

익명 사용자의 이미지

답변감사합니다. 그렇다면 p1-p2 의 결과 값은 데시멀 값으로 4가 되야하는 건가요? 결과값이 1이 나와서요.
반대로(p2-p1) 하게 되면 -1이 나오는 군요. 공부하면 할수록 헷갈리네요. 포인터 이자석...

익명 사용자의 이미지

pointer 는 4byte 가 맞는데요

int 형의 pointer 니까.

빼주면 4(pointer)/4(int)=1 이 나오는겁니다.

--;
맞나?.

익명 사용자의 이미지

main()
{
int i;
char *pp1="Hi ! everybody"; <== 저장공간은 공백하고 NULL까지 합쳐서 15바이트가 필요.
char *pp2="Turbo C V2.0"; <== 저장공간은 공백하고 NULL까지 합쳐서 13바이트가 필요.

printf("\n pp1 save at %p", pp1); <== 결과값 0x80485dd
printf("\n pp2 save at %p", pp2); <== 결과값 0x80485e4
printf("\n pp2-pp1 => %d", pp2-pp1); <== 결과값 7 값은 이상없음. 0x80485e4-0x80485e4 하면 7이 나오니까..

}
그런데 "Hi ! everybody"는 0x80485dd부터 0x80485ee 까지 할당받고 "Turbo C V2.0"은 0x80485ef 부터 채워져 나가는것이
맞지 않습니까? 그런데 pp2의 시작 주소값을 보면 0x80485e4입니다. 왜 값이 틀린거죠?

익명 사용자의 이미지

15가 정상 아닌가여???

pp1 save at 0x401044
pp2 save at 0x401053
pp2-pp1 => 15

저는 이렇게 나오는데....

익명 사용자의 이미지

제가 예상한 값도 분명히 15인데 7이 나오더라구요.
혹시 윈도에서 코딩을 하셨나요?
저는 리눅스에서 gcc-2.95.3으로 컴파일 했는데요.

익명 사용자의 이미지

제가 적어놓은 결과는 win2000에서 gcc/cygwin 2.95.3-5에서
테스트 한겁니다.

솔라리스 2.6에서 데스트한 결과론 16이 나오네요...
뭐 어떤 32비트 머신은 4바이트 단위로 주소를 할당한다는데,
이것때문에 16이 나오는게 아닐까 생각되는데요...
pp1이 16바이트(NULL포함) 일 때도 동일하게 16이 나오는 걸로 봐서...

뭐 15나 16이나 하는 거는 별 문제없이 이해되는데요...
7이란거는?????? 흠

pp1의 문자열이 14바이트지요, 여기에 NULL문자 1바이트...
14라 7 * 2 = 14,,,,(????) 허허 별 생각을 다하게 되네요...

pp1의 문자열 길이를 달리해보면서 테스트해 보는 것은 어떤지...
뭔가 일정한 규칙을 얻을수 있지 않을까요...

아쉽게도 저는 지금 리눅스를 날린 상태라서 테스트할 여건이
안되네요.... 근 1년간의 모아두었던 자료를 다 날려버린 충격이란...

흠.... 다른 분들은 어떤지 궁금...
이거 간단히 테스트할 수 있는 거라서...

어떤 결과가 나오는지 궁금하네요...
흠,,, 별 도움이 못된거 같아서^^ 헤헤
전 초보랍니다.

익명 사용자의 이미지

답변감사합니다. pp1에 들어가는 문자의 수를 바꿔주면 규칙적으로 결과값이 바뀌는데 제가 원하는 값은 나오지 않네요.
이론적으로는 pp2의 주소자체에서 pp1의 주소자체를 뺀거라 pp1이 가지는 문자수 많큼 차이가 있어야 하는데 말이죠.
암튼 포인터 이해하기가 너무 어렵네요. 이거라고 생각하면 저고고 저거라고 생가하면 이게 되버리고... ㅤ

익명 사용자의 이미지

-S옵션을 줘서 어셈 코드를 보시죠?...

이론적으로 문자수만큼 차이가 나야 하는 것은 아닙니다.
컴파일러가, 따옴표로 묶인 문자열을 상수 영역에 배치할 때,
어떻게 저장하느냐에 따라 따르겠지요. 이 경우에는 거의 대부분
문자수만큼 차이가 나겠지만요..

참고로 제 linux box에서는 아래처럼 나오네요.. (machine은 그냥 일반
pc, P-III입니다.)

.file "pointer.c"
.version "01.01"
gcc2_compiled.
.section .rodata
.LC0
.string "Hi ! everybody"
.LC1
.string "Turbo C V2.0"
.LC2
.string "\n pp1 save at %p"
.LC3
.string "\n pp2 save at %p"
.LC4
.string "\n pp2-pp1 => %d"
.text
.align 4
.globl main
.type main,@function
main
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $.LC0,-8(%ebp)
movl $.LC1,-12(%ebp)
movl -8(%ebp),%eax
pushl %eax
pushl $.LC2
call printf
addl $8,%esp
movl -12(%ebp),%eax
pushl %eax
pushl $.LC3
call printf
addl $8,%esp
movl -12(%ebp),%eax
movl -8(%ebp),%edx
subl %edx,%eax
pushl %eax
pushl $.LC4
call printf
addl $8,%esp
.L1
leave
ret
.Lfe1
.size main,.Lfe1-main
.ident "GCC (GNU) egcs-2.91.66 19990314/Linux (egcs-1.1.2
release)"

저기서,
.LC0
.string "Hi ! everybody"
.LC1
.string "Turbo C V2.0"
이 두 위치가 바뀌었으면 결과가 minus로 나오겠죠?..

물론 거의 모든 컴파일러에서는 나오는 순서대로 저장하겠지만...

익명 사용자의 이미지

)
서로 다른 포인터 간의 연산은 무의미합니다.

그것은 서로 다른 배열 간의 첨자 거리를 따지는 것 하고 같은 거니까요.

그런 연산은 보통은 하나의 포인터가 가리키는 메모리 블럭내에서의
거리를 계산할 때 사용하는 것이지요.

위 예제와 같은 포인터 연산은 값이 제멋대로 나오는게 당연합니다.
비슷한 예를 하나 들어 드리지요.

[wolf~/temp]$ more c.c
#include
#include
main()
{

char *p1="1234";
char *p2;

int *i1;
int *i2;

p2=(char *)malloc(sizeof(char)*34);

i1=(int *)malloc(sizeof(int)*1);
*i1=3;
i2=(int *)malloc(sizeof(int)*1);
*i2=333;

printf ("p2-p1%d\n",p2-p1);
printf ("i2-i1%d\n",i2-i1);
}

[wolf~/temp]$ ./a.out
p2-p14428
i2-i14

) 황당한가요?
저는 별 문제없어 보이는 데요.

잘 모르겠으면.. 맨위로 올라가서 다시한번 읽어보세용 ^^;

익명 사용자의 이미지

포인터연산에서 중요한것은 하드웨어적(어셈블리 이하)인것을 이해하는것입니
다.

보통 현재 사용하는 PC는 32비트 머신입니다.
그럼 메모리의 기본 연산단위인 WORD는 4byte가 됩니다.
데이터버스가 32비트->4byte(64비트 컴에서는 8byte가 되겠지요)

이 이야기는 아주 중요합니다.
만약
char p[5];
로 할당한다면

실제로 메모리에서 사용되는 byte수는
8바이트 입니다.

그 이유는 4바이트 단위로 연산이 되므로
5바이트를 표현하기 위해서는 2개의 워드기 필요하기 때문이죠.


char p1[5];
char p2[7];

p1-p2는 8값이 나옵니다.(32비트에서)

답변내용중 이러한 것이 있더군요.

char *pp1 = "HI !.....";
char *pp2;

두개를 비교한다.(?)

pp1은 힙에 생성되고, pp2는 스택에 생성됩니다.
두개를 비교하고 포인터 연산을 한다는 것은 시스템에 따라, 현재 수행중인
프로세스들에 따라 모두 달라지게 됩니다.
전혀 쓸모없는 연산이지요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.