[C] 이 소스 에러 현상좀 잡아 주세요.

Fe.head의 이미지

memcpy에서 우측 공백 제거기능을 추가한 함수를 만들었는데..

자꾸 에러가 나네요.

/* memcpy에 우측 공백 제거 기능을 추가한 함수. */
static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    char *  pSrc = (char *) src;
    size_t  i;

    for(i=size-1; 0<=i; --i) {
        if(pSrc[i] != '\0' && !isspace(pSrc[i])) {
            return memcpy((char *)dest, (char *)src, i+1);
        }
    }

    return dest;
}

아래는 에러 코드및 코드내용입니다.

            return memcpy((char *)dest, (char *)src, i+1);

1506-068 (W) Operation between types "void*" and "int" is not allowed. 

컴파일 환경은

AIX 5.1 , VisualAge C++ Professional / C for AIX Compiler, Version 5

입니다.

neogeo의 이미지

의심해볼만 한것은 아무래도 memcpy 의 return type 인거 같습니다.

한번 살펴보십시오.

Neogeo - Future is Now.

doldori의 이미지

혹시 <string.h>를 #include 하셨습니까?
그건 그렇고...
for(i=size-1; 0<=i; --i)
이 부분은 무한 루프일 수도 있습니다. i는 size_t인데 size_t는 무부호형이므로
0<=i는 항상 참이니까요. 유부호형과 무부호형의 혼합 연산은 주의해야 합니다.

Fe.head의 이미지

neogeo wrote:
의심해볼만 한것은 아무래도 memcpy 의 return type 인거 같습니다.

한번 살펴보십시오.

제가 그 생각해봤는데...
아래 doldori님 글을 보고 <string.h>를 안한 사실을 깨달았습니다.

결국 neogeo님 말씀도 맞고 doldori님 말씀도 맞습니다.

답글 올려주셔서 감사합니다. neogeo님 :D

doldori wrote:

혹시 <string.h>를 #include 하셨습니까?
그건 그렇고...
코드:
for(i=size-1; 0<=i; --i)

이 부분은 무한 루프일 수도 있습니다. i는 size_t인데 size_t는 무부호형이므로
0<=i는 항상 참이니까요. 유부호형과 무부호형의 혼합 연산은 주의해야 합니다.


linux서버에서 테스트할때는 include 해놓고
AIX에서는 안했군요.

또한 size 처리도 했네요^^
감사합니다. doldori님 :D

최종 코드

/* 기능설명 : memcpy에 rtrim 기능을 추가한 함수. */
static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    char *  pSrc = (char *) src;
    size_t  i;

    if(size == 0) {
        return dest;
    }

    for(i=size-1; 0<=i; --i) {
        if(pSrc[i] != '\0' && !isspace(pSrc[i])) {
            return memcpy(dest, src, i+1);
        }
    }

    return dest;
}

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

lovian의 이미지

신기하군요..
저 에러를 보고 한참을 생각해봐도 답이 않나왔는데

간단하게 string.h라니..

제가 unix/linux 계열에서 프로그래밍을 해본건 아니라 그런지는 몰라도 저 에러가 뜨는 이유를 좀 알 수 없을 까요?

타입문제로만 보여지는데 말이지요..

-----------------
한글을 사랑합니다.

Fe.head의 이미지

lovian wrote:
신기하군요..
저 에러를 보고 한참을 생각해봐도 답이 않나왔는데

간단하게 string.h라니..

제가 unix/linux 계열에서 프로그래밍을 해본건 아니라 그런지는 몰라도 저 에러가 뜨는 이유를 좀 알 수 없을 까요?

타입문제로만 보여지는데 말이지요..

제가 알기로는
일반적인 C 컴파일러는 소스를 컴파일할때
선언이 안된 함수를 호출하는 소스가 나오면

int형을 반환하는 함수가 있다고 가정하는걸로 알고 있습니다.

그리고 링크하는 과정에서 해당 함수를 찾아봐서 없거나
반환 값이 int형이 아닌 함수이면 에러를 뱉어 내는 걸로 알고 있습니다.

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

eungkyu의 이미지

lovian wrote:
신기하군요..
저 에러를 보고 한참을 생각해봐도 답이 않나왔는데

간단하게 string.h라니..

제가 unix/linux 계열에서 프로그래밍을 해본건 아니라 그런지는 몰라도 저 에러가 뜨는 이유를 좀 알 수 없을 까요?

타입문제로만 보여지는데 말이지요..

C에서 함수 선언을 안했을 때 기본적으로 리턴 타입을 int라 가정합니다.
string.h를 include하지 않아서 컴파일러가 memcpy의 리턴타입을 int라 가정했기 때문이죠
unix/linux 계열과 관계 없이 C에 관한 문제입니다 :)

doldori의 이미지

fe.practice wrote:
최종 코드
/* 기능설명 : memcpy에 rtrim 기능을 추가한 함수. */
static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    char *  pSrc = (char *) src;
    size_t  i;

    if(size == 0) {
        return dest;
    }

    for(i=size-1; 0<=i; --i) {
        if(pSrc[i] != '\0' && !isspace(pSrc[i])) {
            return memcpy(dest, src, i+1);
        }
    }

    return dest;
}

여전히 해결되지 않았는데요.
char a[2], b[2] = " ";
rtrimcpy(a, b, 2);

이것을 실행해 보세요.
혹시 null-terminated string이면 이렇게 복잡하게 하지 않아도 될 텐데요...
Fe.head의 이미지

너무나 부끄럽군요 :oops:

null-terminated string 이면 끝에 null로 끝난다는건가요?
하지만 제쪽에서는 null로 끝나지 않습니다.

null로 끝난다면 간단하다고 하셨는데 어떤 방법이 있는건가요?

많은 도움을 주셔서 감사합니다.

0.99 version 입니다. ^^

#include <string.h>
#include <ctype.h>

static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    char *  pSrc = (char *) src;
    size_t  i;

    for(i=size; 0<i; --i) {
        char    ch = pSrc[i-1];
        if('\0' != ch && !isspace(ch)) {
            return memcpy(dest, src, i);
        }
    }
    return dest;
}

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

ㅡ,.ㅡ;;의 이미지

fe.practice wrote:
너무나 부끄럽군요 :oops:

null-terminated string 이면 끝에 null로 끝난다는건가요?
하지만 제쪽에서는 null로 끝나지 않습니다.

null로 끝난다면 간단하다고 하셨는데 어떤 방법이 있는건가요?

많은 도움을 주셔서 감사합니다.

0.99 version 입니다. ^^

#include <string.h>
#include <ctype.h>

static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    char *  pSrc = (char *) src;
    size_t  i;

    for(i=size; 0<i; --i) {
        char    ch = pSrc[i-1];
        if('\0' != ch && !isspace(ch)) {
            return memcpy(dest, src, i);
        }
    }
    return dest;
}

char ch = pSrc[i-1];
이거 왜넣으셨는지..
----------------------------
아니구나.. [i-1]이지..
그런데..대입하지 않고 포인터로 처리하는게 좋은듯..
그리고 pSrc 선언도 필요 없을듯.


----------------------------------------------------------------------------

doldori의 이미지

fe.practice wrote:
null-terminated string 이면 끝에 null로 끝난다는건가요?
하지만 제쪽에서는 null로 끝나지 않습니다.

null로 끝난다면 간단하다고 하셨는데 어떤 방법이 있는건가요?


다시 생각해 보니 이 코드와 비교해서 별로 다를 것도 없겠습니다.
그냥 무시하세요. ^^;

fe.practice wrote:
0.99 version 입니다. ^^
#include <string.h>
#include <ctype.h>

static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    char *  pSrc = (char *) src;
    size_t  i;

    for(i=size; 0<i; --i) {
        char    ch = pSrc[i-1];
        if('\0' != ch && !isspace(ch)) {
            return memcpy(dest, src, i);
        }
    }
    return dest;
}

거의 된 것 같은데, 생각해 보니 또 한 가지 문제가 있군요. (이제야 생각났습니다. -_-;)
isspace()의 인자는 unsigned char로 표현 가능하거나 EOF와 같은 값이어야
합니다. 그런데 char가 유부호형인 환경에서는 이 조건을 만족하지 않습니다.
예를 들어 EOF가 -1이고 2의 보수를 쓰는 환경에서 ch의 값이 -128 ~ -2인 경우에는
제대로 동작하지 않을 것입니다. 따라서
unsigned char ch = pSrc[i-1];
로 해야 하겠습니다. 아니면
unsigned char *  pSrc = src;
isspace(pSrc[i-1]);

을 쓰시든지요.
Fe.head의 이미지

doldori wrote:

isspace()의 인자는 unsigned char로 표현 가능하거나 EOF와 같은 값이어야
합니다. 그런데 char가 유부호형인 환경에서는 이 조건을 만족하지 않습니다.
예를 들어 EOF가 -1이고 2의 보수를 쓰는 환경에서 ch의 값이 -128 ~ -2인 경우에는
제대로 동작하지 않을 것입니다. 따라서
unsigned char ch = pSrc[i-1];
로 해야 하겠습니다. 아니면
unsigned char *  pSrc = src;
isspace(pSrc[i-1]);

을 쓰시든지요.

웅. :cry:
이렇게 간단한 소스에도 이런 심오한 뜻들이 있군요 ㅠ.ㅜ

이제 version 1.0으로 올려 볼렵니다.

#include <string.h>
#include <ctype.h>

static void * rtrimcpy(void * dest, const void * src, const size_t size)
{
    unsigned char *  pSrc = (char *) src;
    size_t  i;

    for(i=size; 0<i; --i) {
        unsigned char ch = pSrc[i-1];
        if('\0' != ch && !isspace(ch)) {
            return memcpy(dest, src, i);
        }
    }
    return dest;
}

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

익명 사용자의 이미지

isspace는 인자가 int 형이 아닌가요?

혹시 아닌경우가 있다면 어떤 라이브러리에서

그런식으로 쓰는지 알려 주시겠습니까?

doldori의 이미지

Anonymous wrote:
isspace는 인자가 int 형이 아닌가요?

네, 맞습니다. 그래서 isspace(-100) 같은 것이 문제를 일으킬 수 있는 거죠.
ktd2004의 이미지

이건 제가 사용하는 함수입니다.

/*! \brief 스트링의 뒤에 존재하는 공백문자(' ','\\n','\\r','\\v','\\t')를 제거하는
 * 함수. */
char *trimEndSpace( char *buf)
{
	int i;
	int len;

	assert( buf != NULL);

	len = strlen( buf);
	for( i=len-1; i>=0; i--) {
		if( isspace( buf[i])) {
			buf[i] = '\0';
		} else {
			break;
		}
	}
	return buf;
}

참고삼아, 그리고 혹시 제 코드에서는 수정할 부분이 없나싶어서 올려봅니다.
많은 지적 부탁드립니다.

Fe.head의 이미지

KTD님도 아래와 같은 처리가 빠져 있군요.

doldori wrote:

isspace()의 인자는 unsigned char로 표현 가능하거나 EOF와 같은 값이어야
합니다. 그런데 char가 유부호형인 환경에서는 이 조건을 만족하지 않습니다.
예를 들어 EOF가 -1이고 2의 보수를 쓰는 환경에서 ch의 값이 -128 ~ -2인 경우에는
제대로 동작하지 않을 것입니다. 따라서
unsigned char ch = pSrc[i-1];
로 해야 하겠습니다. 아니면
unsigned char *  pSrc = src;
isspace(pSrc[i-1]);

을 쓰시든지요.

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

ktd2004의 이미지

다음 코드에서 "char ch"를 "unsigned" 타입으로 변경해도 결과(OK/NO)는 같습니다.
gcc -v 4.0.2를 사용했습니다.

int main(void)
{
    int i;
    char ch;
    for(i=0;i<255;i++) {
        ch = i;
        printf("[%02x:%03d] : %s\n", i, ch, isspace(ch) ? "OK": "NO");
    }
}

그런데 ctype.h 파일의 isspace의 정의를 따라가던중 다음과 같은 내용의 주석이 나오네요..

/* These are defined in ctype-info.c.
   The declarations here must match those in localeinfo.h.

   In the thread-specific locale model (see `uselocale' in <locale.h>)
   we cannot use global variables for these as was done in the past.
   Instead, the following accessor functions return the address of
   each variable, which is local to the current thread if multithreaded.

   These point into arrays of 384, so they can be indexed by any `unsigned
   char' value [0,255]; by EOF (-1); or by any `signed char' value
   [-128,-1).  ISO C requires that the ctype functions work for `unsigned
   char' values and for EOF; we also support negative `signed char' values
   for broken old programs.  The case conversion arrays are of `int's
   rather than `unsigned char's because tolower (EOF) must be EOF, which
   doesn't fit into an `unsigned char'.  But today more important is that
   the arrays are also used for multi-byte character sets.  */

이 내용이 무슨 의미가 있을 것 같습니다.

좀 더 자세한 설명부탁드리겠습니다. ^^;

doldori의 이미지

KTD wrote:
다음 코드에서 "char ch"를 "unsigned" 타입으로 변경해도 결과(OK/NO)는 같습니다.

char가 무부호형인 환경에서는 당연히 같은 결과를 보입니다.
위에서 말한 것은 char가 유부호형인 환경에 대한 것입니다.
char의 부호 여부는 구현체 의존적이므로 <ctype.h>에 있는 함수를 올바르게
쓰려면 unsigned char로 취급해야 합니다.

KTD wrote:
그런데 ctype.h 파일의 isspace의 정의를 따라가던중 다음과 같은 내용의 주석이 나오네요..

   These point into arrays of 384, so they can be indexed by any `unsigned
   char' value [0,255]; by EOF (-1); or by any `signed char' value
   [-128,-1).  ISO C requires that the ctype functions work for `unsigned
   char' values and for EOF; we also support negative `signed char' values
   for broken old programs.

표준은 이 함수의 인자가 unsigned char로 표현할 수 없거나 EOF가 아닐 경우
그 결과는 undefined라고 밝히고 있습니다. 즉 표준은 이때의 결과를 명시하지
않으며 각 구현체가 알아서 처리하도록 하고 있습니다. 이 문구는 이 구현체가
"broken old programs"를 배려하여 char의 부호 여부에 상관없이 무리없이 동작하도록
구현하였다는 뜻입니다. (-128 ~ 255의 인덱스는 384개가 됩니다.)

   The case conversion arrays are of `int's
   rather than `unsigned char's because tolower (EOF) must be EOF, which
   doesn't fit into an `unsigned char'.  But today more important is that
   the arrays are also used for multi-byte character sets.  */

이것은 내부적인 구현의 문제로 지금 논의와는 별로 관련이 없는 것인데, character
class table을 unsigned char가 아니라 int의 배열로 구현한 이유를 밝히면서
부수적인 결과로 MBCS에 대해서도 쓰일 수 있다고 말하는 것입니다.

댓글 달기

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