메모리에 접근할때는 signed char을 사용할수 없다!?

gurumong의 이미지

안녕하세요 ^^

책을 읽다가 예문에 대한 코드에 대해서 궁금한것이 생겼습니다
아래 코드를 보면 일반 포인터로 넘겨받은 포인터를 대상체의 값에 접근하기 위해서
새로정의한 unsigned char형의 포인터에 주소를 복사후 이것을 이용해서 접근하는데요
책의 설명에는 메모리에 접근할때에는 signed char형이 아닌 unsigned char형을 사용해야한다는데
그 이유가 나와있지 않아서 궁금증을 일으킵니다

/* 두개의 포인터와 대상체 크기를 받아서 복사하는 my_memcpy함수*/
void my_memcpy(void *s1, const void *s2, unsigned int size)
{
    unsigned int i;
    unsigned char *c1 = s1;
    const unsigned char *c2 = s2;
 
    for (i=0; i 가 size 보다 작으면; i++){
        *c1 = *c2;
        c1 += 1;
        c2 += 1;
    }
}

초보자인 제가 스스로 생각하기엔
signed든 unsigned든 그것이 대상체의 비트열 해석에만 관여하고
실제 비트열에 변화를 주는것이 아니기 때문에 별로 상관이 없을꺼라고 생각하는데요

왜 그런거죠? 흠흠흠!

(소스코드내 for문에서 꺽세가 사용되었는데 정상적으로 출력되지 않아서 살짝 자연어로!? 고쳤습니다 --;)

superkkt의 이미지

저도 위 예제에서는 꼭 unsigned char를 써야한다는 이유는 왜 그런지 궁금하네요. 하지만 아래와 같이 문자열을 정수와 비교하는 함수라면 unsigned char를 써야합니다.

int
compare_func(char *string)
{
   if(string[0] == 0x20 || string[1] <= 0x10) {
      ....

위 코드에서 string[1]이 127보다 크면 음수로 인식되어서 if 문이 참이 되어버립니다. 예상했던 결과가 아니겠죠.

이런 경우가 아니라 단지 메모리에 접근할때는 무조건 unsigned char를 써야한다는건 왜 그런지 저도 궁금하네요. 전에 어디서 비슷한 글을 읽은듯한데 메모를 안해놔서 기억이..

다른 고수님들의 답변 기대하겠습니다.^^

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

익명사용자의 이미지

오해인듯 합니다.
signed char로 메모리에 접근해야 한다는 규칙이나 강제 조항은 없습니다.
다만 signed char로 했을 때 위의 분처럼 비교에서 오동작이 일어나거나
shift 연산에서 원치않는 결과를 내기 쉽기 때문에 unsigned char형을 쓰
는게 더 편한게 사실입니다. 버그를 줄이기 위해 만들어진 습관 비슷한 것
으로 생각하시면 됩니다.

doldori의 이미지

명시적으로 그러한 규칙을 강제하지는 않지만, unsigned char로 접근할 때만
잘 정의된 동작을 한다는 결론을 간접적으로 도출할 수 있습니다.
unsigned char의 내부 표현은 padding이 없이 모든 비트가 value bit라는
점이 특징입니다. 즉 trap representation이 없다는 뜻이죠.
실제로 접하기 어려운 환경이지만 예를 들어 signed char로 double형 변수에
접근할 경우 padding bit로 인해 trap representation에 걸릴 수 있습니다.

gurumong의 이미지

답변 감사합니다 ^^
패딩 비트는 값이나 부호에 영향을 주지 않고 추가적인 정보를 표시하는 비트라 알고있습니다
그런데 그런 패딩 비트가 unsigned char의 대상체에는 없음을 표준에서 보장하고 있나요?

doldori의 이미지

예, 그렇습니다.

doldori의 이미지

다시 기억을 더듬어보니 unsigned char를 써야 한다는 강제 조항이 있군요.
예전에 전웅님께서 말씀해 주셨는데 깜빡 잊고 있었습니다.

Quote:

C99 7.21.1 String function conventions

3 For all functions in this subclause, each character shall be interpreted
as if it had the type unsigned char (and therefore every possible object representation
is valid and has a different value).


익명사용자의 이미지

으음... 잘못 적었군요.
"signed char로 메모리에 접근해야 한다는 규칙이나 강제 조항은 없습니다."
가 아니고
"unsigned char로 메모리에 접근해야 한다는 규칙이나 강제 조항은 없습니다."
입니다.

gurumong의 이미지

답변 해주신 분들 감사합니다 (__)
매번 여기에 질문을 올릴때마다 많은걸 얻어가네요~!

전웅의 이미지

엉뚱한 방향으로 흘러가던 논의가 doldori 님 덕에 제자리를 찾았군요.

unsigned char 는 모든 bit 를 투명하게 볼 수 있는 특성을 제공합니다.
즉, 다른 type 은 내부 비트의 일부를 값을 표현하기 위한 용도가 아닌
다른 용도로 사용할 수 있으나 unsigned char 는 이것이 허락되지
않습니다.

따라서, 임의의 메모리에 바이트 단위로 접근해 값을 다룰 때에는 반드시
unsigned char 를 사용해야 full portability 를 얻을 수 있는 것입니다.
또한, 그와 같은 이유로 signed char 가 표현할 수 있는 값의 개수보다
unsigned char 가 표현할 수 있는 값의 개수가 많다는 사실에도 유의할
필요가 있습니다. signed char <-> unsigned char 사이의 값 변환이 1:1
로 이루어질 수 "없는" 경우도 있음을 의미합니다.

이와 같은 이유로, 표준이 바이트 값에 접근해야 하는 경우나 문자에
접근해야 하는 경우 (예: mem*(), str*() 함수들) 에는 모두 unsigned char
로 접근하도록 요구하고 있습니다. 책에서는 memcpy 함수를 흉내내는
것이기 때문에 그런 사항을 반영해 unsigned char 를 사용했습니다.

예전에 이곳에서도 비슷한 논의가 있었던 것으로 기억합니다만, 꼭 padding
bit 가 아니어도 null character 의 정의에 의해 문제가 될 수 있는 경우가
있습니다. signed char 는 1s' complement 표현이나 sign-magnitude
표현에서 -0 을 가질 수도 있습니다 - 이 경우 sign bit 가 1 이 됩니다.
하지만, null character 의 정의는 (sign bit 포함해) 모든 비트가 0 이길
요구하고 있습니다. 즉, -0 은 null character 가 될 수 없는 것입니다.
따라서 이를 올바르게 구분해내기 위해서는 unsigned char 로 접근해야
하는 것입니다.

p.s. 제 기억으로는 최소한 padding bit 에 대한 내용, unsigned char 가
padding bit 를 갖지 않는다는 내용은 책에서 다룬 것으로
기억합니다만...

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

gurumong의 이미지

앗 답변 해주신 여러분들 감사합니다~!

댓글 달기

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