C 기초 질문입니다.

하하의 이미지

안녕하세요. ^^;

main() {

    char *a;    // char 형 하나를 가리킬수 있는 주소 공간이 확보된다.

    a = "insert stream";  // 주소를 heap 영역에 할당 하지 않은 
                         // 상태에서 문자열을 집어 넣는다.
    printf(" %s \n", a);

}

이런식으로 메모리를 할당 하지 않는 상태에서 문자열을 다룰때

어떤 문제가 생길까요?

main() {
    char *a;
    
    a = "insert stream";
  
     printf(" %s ", a);

     b();

}

b() {
    char *b;

    b = "insert stream";

    printf(" %s ", b);

}

머 이런식으로 값을 집어 넣어도 깨지거나 이런 건 보질 못했는데.

그 주소가 공식적으로 할당 되어 지지 않은 것이기 때문에 다른 무엇

인가에 의해 그 값이 깨어 질 수 있다고 생각 해야 되는 건가요?

그럼 즐거운 하루 되시고요.. 수고 하세요....^__^;;

jj의 이미지

정상적인 코드로 상수영역에 할당을 한 상태입니다.

--
Life is short. damn short...

alfalf의 이미지

% strings 프로그램명하시면 보다 명확해 지실겁니다.

하하의 이미지

jj wrote:
정상적인 코드로 상수영역에 할당을 한 상태입니다.

그렇다면 왜.. malloc을 사용하나요?

char* a 이렇게 선언만 한 상태에서

a = "test stream" 이런식으로 넣는다면...

test stream 의 시작 주소가 1000번 이라고 할때....

1000번 't', 1001번 'e', 1002번 's' .... 이런 식으로 들어 갈텐데...

char* a 라 함은 시작 주소만 1000번을 할당한 상태라....

1001, 1002,.... 등등 뒤에 따르는 주소는 다른 무엇인가가 사용할때

덮어 씌워 질 수 있다는 뜻 아닌가요?? 그래서 malloc을 사용하여

1000, 1001, 1002... 등등의 주소공간을 a에 할당하여 다른 무엇에

의해 쓰여 질 수 없도록 보장하는 것 아닌가요??

제 생각이 무엇이 틀린 건가요??

^__^..... 꼭 좀 알려주세요....

그럼 즐거운 하루 되세요....

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

불량청년의 이미지

상수역역은 메모리 한계가 있습니다.

기억이 안나는데 64K로 알고 있는데 맞나요?

아뭍은 그 이상의 데이터를 메모리에 쓰기 위해선

힙에 써야 합니다. 그래서 메모리 할당 함수를 써서

힙에 잡아 주는 것이죠.

H/W가 컴퓨터의 심장이라면 S/W는 컴퓨터의 영혼이다!

sangwoo의 이미지

하하 wrote:
jj wrote:
정상적인 코드로 상수영역에 할당을 한 상태입니다.

그렇다면 왜.. malloc을 사용하나요?

char* a 이렇게 선언만 한 상태에서

a = "test stream" 이런식으로 넣는다면...


위의 코드는 a가 가리키는 주소에 test stream이란 문자열을 대입하는 것이 아니고, 상수영역에 잡혀있는 string의 주소(즉 제일 첫번째 character의 주소)를 a에 대입한다는 의미입니다. 즉 'test stream" 이라는 코드를 적는 순간, 적법한 메모리(물론 이 경우는 스택도 아니고, 힙도 아니지만..)에 그 string이 allocate되는 겁니다.
char *a; 이후에 a의 주소(어딘가겠죠) 에 문자열을 넣어서 segmentation fault가 나오는 것을 보시고 싶으시다면,
strncpy(a, "test stream", 12);

이런식으로 하시면 됩니다. 차이를 아시겠죠? ^^

----
Let's shut up and code.

lsj0713의 이미지

하하 wrote:
jj wrote:
정상적인 코드로 상수영역에 할당을 한 상태입니다.

그렇다면 왜.. malloc을 사용하나요?

동적으로 메모리를 할당하기 위해서 입니다. 좀 더 자세하게 말하면, 실행시간 도중에 원하는 크기의 메모리를 할당받기 위해서 입니다. 배열로는 단지 미리 정해진 크기의 메모리만을 할당할 수 있을 뿐입니다. 사용해야 될 메모리의 크기가 가변적이라면 malloc를 사용해야 합니다.

하하 wrote:

char* a 이렇게 선언만 한 상태에서

a = "test stream" 이런식으로 넣는다면...

test stream 의 시작 주소가 1000번 이라고 할때....

1000번 't', 1001번 'e', 1002번 's' .... 이런 식으로 들어 갈텐데...

char* a 라 함은 시작 주소만 1000번을 할당한 상태라....

아닙니다. a에는 단지 시작주소 1000번만 저장되어 있을 뿐입니다. malloc는 메모리 할당에 실패하면 실패했지, 절대 다른 용도로 사용되는 공간과 겹치는 메모리 주소를 리턴하지 않습니다. malloc가 엉뚱한 곳에 메모리를 잡지 않게 해주는 것은 malloc를 제작하는 컴파일러 제작자의 의무중 하나입니다.

하하 wrote:

1001, 1002,.... 등등 뒤에 따르는 주소는 다른 무엇인가가 사용할때

덮어 씌워 질 수 있다는 뜻 아닌가요?? 그래서 malloc을 사용하여

1000, 1001, 1002... 등등의 주소공간을 a에 할당하여 다른 무엇에

의해 쓰여 질 수 없도록 보장하는 것 아닌가요??

malloc와 마찬가지로, 문자열 상수나 배열이 사용하는 메모리 공간도 내부적으로 서로 겹치지 않도록 되어 있습니다. 절대 malloc와 겹칠까 걱정할 필요가 없습니다.

질문하신 내용을 보니, 문자열 상수에 대해서 좀 더 설명을 해야 될 것 같습니다.
C99 표준문서를 인용하겠습니다.

Quote:

C99 6.4.5 String literals P5

...The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.

문자열 상수는 정적 기억 수명을 갖는 char형 배열로 취급됩니다. 그러므로 프로그램 전체에 걸쳐서 항상 존재하는 것이 보장이 됩니다. 다만 문자열 상수의 내용을 수정하는 행위는 undefined behavior를 갖습니다.

ifyou의 이미지


main()
{
    char* s;

     s="test";

     printf("%s\n",s);

     strcpy(s,"hello");    // <<======

}

상수는 읽을 수만 있습니다. 읽고 쓰고 하려면 malloc으로 메모리를

할당 받아야 합니다.

하하의 이미지

Quote:

상수는 읽을 수만 있습니다. 읽고 쓰고 하려면 malloc으로 메모리를

할당 받아야 합니다.

그렇다면...

main()
{

    char *a;

    a = "test stream";

}

여기서 "test stream" 은

const static char*

로 생각 해도 되겠네요?

속성이 const 로 변경 불가에

scope는 데이터 영역에 위치 <- static

^^....

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

wireworm의 이미지

할당된 메모리는 a를 위한 4바이트뿐이지, 문자열 "test stream" 를 위해서는 메모리가 할당되지 않고 "test stream" 라는 표현은 메모리의 남는 곳에 문자열 test stream 와 0을 차례대로 집어넣고 't'의 시작 주소을 리턴합니다.

2000 't'
2001 'e'
2002 's'
2003 't'
...
20xx '\0'

a는 't'의 주소를 가지게 되지만, 2000부터 20xx번지까지가 메모리 할당된 것은 아닙니다.

char *a;
a = "test stream";
은 에러경향이 있는 코드가 됩니다.

char* s;
s=new char[6]; // s -> 2001
s="hello"; // s -> xxxxx: "hello"
printf("%s\n",s);
delete[] s;

s가 new로 할당받은 메모리가 떠버립니다. (dangling pointer)

lsj0713의 이미지

wireworm wrote:
할당된 메모리는 a를 위한 4바이트뿐이지, 문자열 "test stream" 를 위해서는 메모리가 할당되지 않고 "test stream" 라는 표현은 메모리의 남는 곳에 문자열 test stream 와 0을 차례대로 집어넣고 't'의 시작 주소을 리턴합니다.

2000 't'
2001 'e'
2002 's'
2003 't'
...
20xx '\0'

a는 't'의 주소를 가지게 되지만, 2000부터 20xx번지까지가 메모리 할당된 것은 아닙니다.

char *a;
a = "test stream";
은 에러경향이 있는 코드가 됩니다.

아닙니다. 제시하신 코드는 전혀 문제가 없는 코드입니다. 또한 다음과 같은 사용도 가능합니다. ("string"에 주목하십시오)

char buf[100];
strcpy(buf, "string");

ps. 제가 글을 올린 다음에 덧붙이신 내용에 대한 첨언입니다.

wireworm wrote:

char* s;
s=new char[6]; // s -> 2001
s="hello"; // s -> xxxxx: "hello"
printf("%s\n",s);
delete[] s;

s가 new로 할당받은 메모리가 떠버립니다. (dangling pointer)

그러나 다음 코드는 전혀 문제가 없는 코드가 됩니다.

char* s;
s = "hello"; // s -> xxxxx: "hello"
s = new char[6]; // s -> 2001
strcpy(s, "world");
printf("%s\n",s);
delete[] s;

참고로, 위의 코드는 C 코드가 아니라 C++ 코드입니다.

댓글 달기

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