아주 내 머리르 혼란하게 했던 문제인데여...

stypr의 이미지

#include<stdio.h>

int main()
{
        char a[10] = "aaa";
        char b[10] = "aaa";

        char *c="aaa";
        char *d="aaa";


        if("aaaa" == "aaaa")
                printf("^^");

        if(a == b)
                printf("a == b");

        if(c == "aaa")
                printf("c == aaa");

        if(c == d)
                printf("=+=");

}

전 씨를 배울때 문자열은 == 로 비교가 불가능하다고 배웠져..
헌데.. 배열빼고는 다 동작을 하더군여..

a ==b 만 안되고..

포인터값을 가지고 비교하는거 같은데영..
"aaa" == "bbb" 는 왜 될까여 -_-;;

아 머리가 하얗게 변하는데여.. -_-;;;
씨 몇년간 하믄서 -_-; 이런 기초에서 헷갈려 하다니 ㅠ.ㅠ 처절하군여

답변 부탁드립니다..

qudals의 이미지

다른 것을 잘 이해가 안되지만 P
두번째 비교문만 아는데 까지 설명하겠습니다.

배열로 선언된 a[10]에서
a만을 사용하게되면
a[0]의 포인터를 가리키게 됩니다.
그래서 a 와 b를 비교하는 것은
&a[0] 와 &b[0] 을 비교하는것이 되어 아무 의미 없는 일이 됩니다.
또한 다르게 선언된 두 배열이 같은 메모리 공간에 할당되지 않기 때문에
a와 b는 같지 않습니다.

그리고 포인터변수는 선언만 하는 것으로 완전하지 않습니다.
malloc 등을 사용하여 실제 메모리상의 주소를 가리키게 하여야 합니다.
아마 그런 이유로 네번째 비교문이 포인터 변수에 들어있는 값-쓰레기값 을 이용하는것 같습니다.

^^

이한길의 이미지

배열은 컴파일 할때 메모리상의 자리를 각각 다르게 배정 받았구요..

나머지 포인터와 그 외에 if문 안에 있는 "aaa"라는 문자열은

메모리 상에 하나의 장소에 위치해 있기 때문일 겁니다.

어짜피 상수로 정의된 거니까요...

다음의 예제를 보시고 컴파일해서 결과를 보시면 명확해질 듯 합니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

int main() 
{
        char *c = (char *)malloc(10);
        char *d = (char *)malloc(10);
        strcpy(c, "aaa");
        strcpy(d, "aaa");
        if ( c==d )
                printf("equal");
        
        if ( c=="aaa" )
                printf("equal2");
        system("PAUSE");	

}

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

이한길의 이미지

제가 글을 적는 동안 .... 글을 올리셨군요.. 첫글인줄 알았는데.. ㅡㅡ;
건 그렇구요.. 마지막에 다음과 같이 적으셨는데요..

Quote:
그리고 포인터변수는 선언만 하는 것으로 완전하지 않습니다.
malloc 등을 사용하여 실제 메모리상의 주소를 가리키게 하여야 합니다.
아마 그런 이유로 네번째 비교문이 포인터 변수에 들어있는 값-쓰레기값 을 이용하는것 같습니다.

그게 아니구요.. 코드 내부에서 "aaa"라고 하는 부분들은 그 크기에 맞게

그 마다 메모리를 할당 받고 위치를 가르키게 됩니다. 단 변경은 불가능하지요..

그래서 컴파일러가 자신의 재량것 같은 위치를 가르키게 했는지도 모른다는 생각이 드는군요.

물론 제가 컴파일러 소스를 분석을 해보지는 않아서 장담은 못하겠지만 그럴것 같다는 생각입니다.

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

pynoos의 이미지

위의 code의 filename을 a.c 라고 한다면..

gcc a.c -fwritable-strings

이라구 옵션을 주신뒤에 다시 해보세요.

compiler가 optimization을 할때, constant string의 경우 공유하도록 되어 있습니다.

VC++에도 option 어딘가에 있을 겁니다.

skjk의 이미지

JAVA의 경우 같은내용의 스트링상수가 사용되면 해당 스트링을 공유하는게 명시되어있습니다.

C의 경우 스트링상수공유가 명세서에 있지는 않지만 컴파일러에 따라 최적화를 하면서 스트링을 공유해서 사용할 수 있습니다.

하지만 명세서에 있지 않는 내용이므로 컴파일러에 따라 다르게 동작할 수 있는 부분이기 때문에 저 방식으로 비교하지 않는 것이 좋습니다.

new5244의 이미지

Quote:
전 씨를 배울때 문자열은 == 로 비교가 불가능하다고 배웠져..
헌데.. 배열빼고는 다 동작을 하더군여..

== 연산자로 문자열 비교가 불가능 하다는 말은 프로그램에서 문자열에 대해 == 연산을 사용할 수 없다는 말이 아니라
우리가 예상하는 문자열 연산의 결과가 나오지 않는 다는 말입니다.

C 언어에서 " " (인용부호, string 이라고 하죠) 로 둘러 쌓인 모든 상수는
최종적으로 메모리의 주소로 변환됩니다.

즉, 아래와 같은 문장은

Quote:
if("aaaa" == "aaaa")
printf("^^");

문자열 "aaaa" 와 "aaaa" 가 서로 같은 string 인지 비교하는 게 아니라
"aaaa" 가 저장된 주소와 ( == 왼쪽에 있는) "aaaa" 가 저장된 주소( == 오른쪽에 있는) 주소가 같은지 비교 하는 문장입니다.

test 님께서 제시한 소스코드의 비교문을 살펴보면

Quote:
if("aaaa" == "aaaa")
printf("^^");

"aaaa" 와 "aaaa" 가 저장된 주소가 같은가? 를 묻는 비교문이니..
당연히 같다고 나오는 것이구요.
(요즘 컴파일러는 워낙 기능이 좋아서 기본적으로 이정도의 Optimize 는 해줍니다)

Quote:
if(a == b)
printf("a == b");

배열 a 의 시작 주소와 b 의 시작 주소가 같은가? 는 당연히 같지않겠구요..

Quote:
if(c == "aaa")
printf("c == aaa");

c 의 값과 "aaa" 가 저장된 메모리 주소가 같은가? 에서는...
초기에 c 가 선언될때 char * c = "aaa" 라고 되 있었으니..
당연히 컴파일러에서 알아서 Optimize 했을테니 같은 주소가 할당 되었을것이구요

Quote:
if(c == d)
printf("=+=");

d 역시 char * d = "aaa" 라고 되어 있으니...
c 와 d 는 결국에는 같은 주소를 가리키니 같다고 나오는 거겠죠..

즉, 위 예에서 == 연산자는
문자열을 비교하는 것 이 아니라
메모리 주소를 비교하는 것이기 때문에 그런 결과가 나오는 겁니다.

c 에서 문자열을 비교하시려면 strcmp() 계열 함수를 사용해야 합니다.

from saibi

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.