C 소스코드 질문...

rkskekfkakqktk의 이미지

최근 프로그래밍을 시작한 초보인데, 코드 분석 중 궁금한 점이 있어 질문 올립니다.

아래 코드를 보았을 때, 어떤 코드임이 이해되었는데... 특정 부분을 확인해 보고 싶어졌습니다.

  while ((opt = getopt_long(argc, argv, OPT_STRING,                                                               
          long_options, &oindex)) >= 0)                                                                           
 
    switch (opt) {                                                                                                
 
      case 'A': {                                                                                                 
          u8* x = (u8*)strchr(optarg, ':');
          if (!x) FATAL("Credentials must be in 'user:pass' form.");                                              
          *(x++) = 0;                                                                            
          auth_user = (u8*)optarg;                                                                                
          auth_pass = x;                                                                                          
          auth_type = AUTH_BASIC;                                                                                 
          break;                                                                                                  
        }     

위의 코드 중 *(x++) = 0; 이란 부분이 어떤 의미인지 이해는 되었지만, 한번 확인해 보고 싶은 생각에 아래의 간단한 코드를 작성해 컴파일 해보았습니다.

#include <stdio.h>
#include <string.h>
 
void main(void)
{
 
        unsigned char* y = NULL;
        unsigned char* z = "abc:567";
        unsigned char* x = (unsigned char*)strchr(z, ':');
 
        *(x++) = 0;
 
        y = x;
 
        puts(y);
}

그런데 위의 코드가 컴파일은 잘 되는데... *(x++) = 0 에서 세그멘테이션 폴트가 납니다.
무슨 문제가 있는지 자세한 설명 해 주실 수 있는 분께 부탁 좀 드리겠습니다.
감사합니다.

yukariko의 이미지

*(x++) = 0 은 x가 가리키는 주소에 값을 0으로 쓰고, x가 저장하는 주소를 증가시킨다는 의미입니다.

아래 예제가 런타임에러가 난 이유는
"abc:567" 은 문자열 상수로, 읽기전용 공간에 들어가 있기 때문에 값을 대입할 수 없습니다.
테스트를 하고싶으시다면

char z[] = "abc:567";

로 선언하고 하시면 될것입니다.

위 선언은 z가 잡힌 주소에 문자열 상수를 복사한다는 의미입니다.

예제의 경우를 예로들자면

x가 가리키는 주소는 ':' 가 들어있는 주소겠죠. 그리고
*(x++) = 0;
에 의해 ':' 대신 0이 들어가고, x는 증가하므로 '5' 에 해당하는 주소를 가리키게 됩니다.

익명 사용자의 이미지

답변 감사드립니다.

그런데 궁금한 점이 있습니다.
(제가 잘 몰라서 그럴수도... ㅠㅠ)

*(x++) = 0 ;
를 해석하자면...
x의 주소 값을 1 증가시킨 후, 그 주소에 0을 저장하라는 의미 아닌가요?

만약 설명해 주신대로 되려면 코드가
(*x)++ = 0;
이 되어야 하는거 아닌가 싶습니다...

설명 좀 부탁 드리겠습니다.

yukariko의 이미지

x++와 ++x 의 차이를 생각해보세요.
현재 주소가 가리키는 값에 0을 저장하고 현재 주소를 1 증가시키는 코드입니다.

(*x)++ = 0;
이런 표현은 존재하지 않습니다.

익명 사용자의 이미지

친절한 답변 감사드립니다^^

하나만 더 여쭤보면.

문자열이라 읽기 영역에 문자열이 저장된다고 하셨는데...
그래서 문자열을 배열에 저장하라 하셨는데...

배열 대신 포인터에 메모리를 할당하면 포인터로도 처음 문의했던 코드가 가능할까요?

yukariko의 이미지

배열대신 포인터를 사용한다면
다음과 같은 방법이 있겠네요.

char *a = malloc(10);
strcpy(a,"abc:567");

만약 이 방법이 아니라 아래와 같은 코드를 생각하고 계셨다면,
포인터에 대한 공부가 더 필요해 보입니다.

char *a = malloc(10);
a = "abc:567";

익명 사용자의 이미지

친절한 답변 매우 감사 드립니다.

편안한 밤 되세요...

shint의 이미지


이런 결과가 있습니다.

http://codepad.org/ 에서는 Segment Fault 가 나고.
Visual Studio 2013 Community 에서는 그냥 됩니다.

#include <stdio.h>
#include <string.h>
 
void main(void)
{
	unsigned char* z = (unsigned char*)"abc:567";
	int i = 0;
 
	for (i = 0; i<7; i++)
	{
		printf("%c\n", *(&z[i]));
	}
 
	*(unsigned char*)(&z) = 'Z';
	printf("--------------\n");
	printf("%s\n", z);
	printf("--------------\n");
	printf("%c\n", z);
	printf("--------------\n");
 
	*((unsigned char*)&z + 1) = 'X';
	printf("--------------\n");
	printf("%s\n", z);
	printf("--------------\n");
	printf("%c\n", z);
	printf("--------------\n");
	printf("%c\n", *((unsigned char*)&z+1));
	printf("--------------\n");
 
	for (i = 0; i<7; i++)
	{
		printf("%c\n", *(&z[i]));
	}
 
}
 
 
c
	:
5
6
7
--------------
 
--------------
Z
--------------
--------------
 
--------------
Z
--------------
X
--------------

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

익명 사용자의 이미지

대체 뭐를 의도한 예제인지는 모르겠으나
잘못된 코드인건 당연하거니와
굉장히 위험한 코드입니다.
허용되지 않은 공간에 마구 읽기와 쓰기를 하는군요.

댓글 달기

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