포인터가 가지고있는 데이터를 넣을때 질문..

rriiaa의 이미지

int main()
{
int i, index;
char *key;
char table[5];
memset(table,0,sizeof(table));
key=(char *)malloc(sizeof(strlen(key)+1));

for (i=0;i<5;i++) {
index =sizeof(hashtable)/sizeof(table[0]);
scanf("%s",key);
table[i]=*key;
}

}

이런 코드가있습니다.. 코드를 짤라서 그런데
key는 포인터로 사용이 되어야해서 그렇습니다.

여기서 질문이 key가 가지는(?) 데이터를 table에 넣고 싶은데
저렇게 하니 컴파일은 잘되는데 막상 값을 넣어보니
segmantation fault가 나는군요...어떻게 해야 할까요?ㅜㅜ

익명 사용자의 이미지

key=(char *)malloc(sizeof(strlen(key)+1));

이 코드는 이상하군요. strlen의 반환값은 size_t 타입이고, 이는 구현환경에 따라 결정되는 어떤 무부호(unsigned) 정수형입니다.
거기에 대고 sizeof를 적용하면 뭐 구현환경에 따른 값이 나오겠죠. 아마도 32비트 환경이면 4, 64비트 환경이면 8? 모르긴 몰라도 아마 의도하신 것보다 작은 메모리가 할당될 겁니다.
이게 직접적인 에러의 원인은 아닐 테지만, sizeof(size_t) + 1을 해도 동일한 결과를 얻을 수 있다는 점에서 뭔가 프로그래머의 의도와 일치하지 않는 것 같군요.

key가 잘 초기화된 null-terminated 문자열을 가리키고 있으며 그 문자열을 담을 수 있는 메모리를 할당하고 싶다면, sizeof 없이 곧바로 malloc(strlen(key)+1)와 같이 호출하는 것이 맞습니다.
제시하신 코드에서는 key에 초기값이 없긴 한데, 잘려진 코드라고 하셨으니 아마도 생략된 거겠죠. 원본 코드에도 key에 초기값이 없으면 그게 segmentation fault의 직접적인 원인이 됩니다. 초기화되지 않은 쓰레기값 포인터를 strlen에 넘기면 안 됩니다.

그 외에도 솔직히 제시하신 코드에 대해 드릴 말씀이 여럿 있는데(부주의한 scanf 사용이라던가) 당장 segmentation fault가 뜨는 원인과는 무관해 보이니 넘어가겠습니다. 연습 목적이라면 큰 문제 없을 것 같기도 하고요.

익명 사용자의 이미지

셋째줄의 sizeof(size_t) + 1sizeof(size_t)로 정정합니다.

rriiaa의 이미지

하고자 하는것은.. 어떠한 문자열 포인터를 입력으로 받아서 입력받은 포인터로 어떠한 함수를 통해서

그 포인터가 배열에 저장되게 하는 것인데..

우선 malloc부분은 이해가 되서 고쳐야 할것 같습니다 ^^

궁금한게.. 포인터로 계속 연산을 하더라도 초기화가 필요한거 였군요..

char *p;
char s;
p=&s;

라고 하고 p 를 가지고 계속 연산을 하고 함수의 인자로 전달해도 초기화가 필요한건가요?
아니면..초기값 null을 넣으라는 말씀이신가요?

익명 사용자의 이미지

초기화하지 않았더라도 그 값을 사용하지 않았으면 문제가 없습니다.(권장할 만한 스타일은 아니지만요.)

제시하신 코드의 문제점은 strlen 함수에 초기화되기 전의 key가 넘겨졌다는 거죠. 원본 코드에서도 그랬다면 고치셔야 합니다.

rriiaa의 이미지

많이 배우고 갑니다. 감사드립니다^^

mydream의 이미지

만약 그걸 원하신 것이라면, table[i]도 포인터여야 합니다. 즉 table은 포인터 배열(*table[])이여야 하는 것이죠.

rriiaa의 이미지

그렇다면 일반 배열에는 포인터변수의 데이터를 직접 넣을수 없는건가요?

익명 사용자의 이미지

table[i]=*key 라고 해버리면 key가 가리키는 문자열의 "첫 문자"를 table[i]에 저장한다는 의미입니다.

C언어에서 문자열은 단어 그대로 문자의 배열에 불과하고, 특히나 C언어는 배열을 통째로 다루는 게 불편한 편이어서 이런 식의 가변 길이 문자열을 다루기가 좀 짜증스럽습니다. 예컨대 C언어에서 이미 있는 문자열의 복사본을 힙에 생성하려면 strlen-malloc-strcpy의 3콤보를 거쳐야 하죠. C++에서는 string, vector 등의 지원으로 좀 나아지긴 했습니다만 어쨌건 지금 C를 쓰고 계신 건 그럴 만한 이유가 있어서겠죠.

익명 사용자의 이미지

> 이미 있는 문자열의 복사본을 힙에 생성하려면 strlen-malloc-strcpy의 3콤보를 거쳐야 하죠.
strdup()

익명 사용자의 이미지

꽤나 보편적인 대안이기는 합니다만 유감스럽게도 비표준이죠.

C 표준 라이브러리가 strdup을 포함하지 않은 이유가 궁금했던 적도 있었습니다만, 사실 strlen-malloc-strcpy로 자연스럽게 구현되는 걸 굳이 래핑해서 또 다른 라이브러리 함수를 만들 필요는 없었을지도 모르겠습니다.
아무튼, 이식성이 중요한 프로그래밍이라면 제공된 strdup 함수를 사용하는 것보다는 직접 구현해 쓰는 편이 낫지 않을까요.

rriiaa의 이미지

네.. 굳이 C를 써야하는 이유가 있어서 ㅜㅜ

그렇군요.. 3단콤보로 사용해야겠네요 감사합니다!!

댓글 달기

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