void 형 포인터에서 ((char *)pv)++ 이 맞나요, (char *)pv++ 이

yangam의 이미지

void *pv;
char *ps, s[] = "ABCDEFG";

ps = s;
pv = ps;

((char *)pv)++    // warning: use of cast expressions as lvalues is deprecated 발생
(char *)pv++       // 어떤 경고 메세지도 없이 잘 동작함

이 일부의 소스는 터보 C 정복 639 페이지에 나온 책의 예제인데요..
분명히 책에서는 첫번째인 ((char *)pv)++ 로 해야된다고 하던데...
실제로 해보니, 동작은 제대로 되지만 경고가 발생하네요.

저자분이 실수하신건가요?

컴파일러는 gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) 입니다.

답변 부탁드려요;;

(char *)pv++ 이 맞는건지, 아니면 ((char *)pv)++ 이 맞는건지....

근데, 연산자 순위대로 해석하자면 2 개가 어떻게 다르게 되는거죠?

괄호가 가장 높은 연산 순위를 갖으므로.. (char *) 로 pv 를 형변환 한 후에

pv의 주소 값을 1 * sizeof(char) 만큼 증가시키는 것으로 같은것 아닌가요?

분명히, 아닌 것 같은데... ;;;;

답변 부탁드립니다.

angpoo의 이미지

pv++;만 하면 pv값이 1올라갑니다.
(char*)pv++;는
printf("%s", (char *)pv++); 이런 정도로 쓰이겠죠.

kuma의 이미지

(char*)p++ 이것은 (char*)(p++) 과 같습니다.

p 가 void* 이므로 size 정보를 알수가 없으므로 이건 절대 될수가 없다고 봅니다.

그리고
((char*)p)++ 이부분은 언뜻보기에는 정확한 표현 처럼 보이지만....

((char*)p) 이 표현자체가 r-value 를 뜻하고 있습니다.

cdpark의 이미지

yangam wrote:
이 일부의 소스는 터보 C 정복 639 페이지에 나온 책의 예제인데요..
분명히 책에서는 첫번째인 ((char *)pv)++ 로 해야된다고 하던데...
실제로 해보니, 동작은 제대로 되지만 경고가 발생하네요.

저자분이 실수하신건가요?

"터보 C 정복"이 포인터에 대해서라면 아주 훌륭한 책이지만, C 언어 표준을 익힌다거나 C 문법을 익히는 데에도 좋은 책은 아닙니다.

"터보 C"라는 특정 구현에서 잘 돌아가는 방법이 나와있습니다만, 그게 부작용)side effect)에 의한 것일 수도, 아니면 나름대로의 구현에 의한 것인지가 구분되어 있지 않습니다.

옥과 티를 골라가며 읽어야 할 책입니다.

ㅡ,.ㅡ;;의 이미지

yangam wrote:
void *pv;
char *ps, s[] = "ABCDEFG";

ps = s;
pv = ps;

((char *)pv)++    // warning: use of cast expressions as lvalues is deprecated 발생
(char *)pv++       // 어떤 경고 메세지도 없이 잘 동작함

이 일부의 소스는 터보 C 정복 639 페이지에 나온 책의 예제인데요..
분명히 책에서는 첫번째인 ((char *)pv)++ 로 해야된다고 하던데...
실제로 해보니, 동작은 제대로 되지만 경고가 발생하네요.

저자분이 실수하신건가요?

컴파일러는 gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) 입니다.

답변 부탁드려요;;

(char *)pv++ 이 맞는건지, 아니면 ((char *)pv)++ 이 맞는건지....

근데, 연산자 순위대로 해석하자면 2 개가 어떻게 다르게 되는거죠?

괄호가 가장 높은 연산 순위를 갖으므로.. (char *) 로 pv 를 형변환 한 후에

pv의 주소 값을 1 * sizeof(char) 만큼 증가시키는 것으로 같은것 아닌가요?

분명히, 아닌 것 같은데... ;;;;

답변 부탁드립니다.


((char *)pv)++ 이 맞는데
(char *)pv++이 틀렸는데..


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

ixevexi의 이미지

Quote:

(char*)p++ 이것은 (char*)(p++) 과 같습니다.

p 가 void* 이므로 size 정보를 알수가 없으므로 이건 절대 될수가 없다고 봅니다.

그리고
((char*)p)++ 이부분은 언뜻보기에는 정확한 표현 처럼 보이지만....

((char*)p) 이 표현자체가 r-value 를 뜻하고 있습니다.

제가 잘 몰라서 그렀습니다만....

우선 포인터형의 크기는 모두 같은것 아닌가요?

void * a 나 int *b 나 typedef struct a{} * c 나 다 똑같은 싸이즈 아닌가요?
적어도 포인터 연산에서는 결과는 맞게될듯 한데요?

그리고 ((char*)p) 이 표현 자체가 왜 r-value죠 <- 이 질문 하려고 끼어들었었습니다. :oops:

제가 알기론 r-value는 임시적인 값이나 고정된 상수의 의미로 알고 있는데
저건 분명히 왼쪽 항에 대입되어도 되는 식인거 아닙니까?

예를 들어

 void * a;
 char * asdf = "asdf"
 
 ((char*)a) = asdf;

이것이 틀린것인가요? :oops:

C++, 그리고 C++....
죽어도 C++

moonzoo의 이미지

Quote:
우선 포인터형의 크기는 모두 같은것 아닌가요?

void * a 나 int *b 나 typedef struct a{} * c 나 다 똑같은 싸이즈 아닌가요?
적어도 포인터 연산에서는 결과는 맞게될듯 한데요?

아마도 잠시 혼동하신것 같습니다만..

포인터 형의 크기는 다 같지만,

" 포인터++ " 의 형태는

해당 포인터의 크기만큼이 아닌

포인터가 가리키는 type의 사이즈만큼

포인터 값을 증가시키라는 의미입니다.

그러므로 가리키는 type의 크기를 반드시 알아야 되죠.

char * pa; ==> pa++은 1byte증가
int * pi; ==> pi++은 4bye 증가

Quote:
그리고 ((char*)p) 이 표현 자체가 왜 r-value죠 <- 이 질문 하려고 끼어들었었습니다.

저도 궁금합니다 ^^

참고로 플그램 돌려봤더니 lvalue가 아닌것은 확실합니다만..

그 원리를 아시는 분은 답변 부탁드립니다.

ixevexi의 이미지

아앗 너무 부끄럽습니다 ^^

Quote:

아마도 잠시 혼동하신것 같습니다만..

포인터 형의 크기는 다 같지만,

" 포인터++ " 의 형태는

해당 포인터의 크기만큼이 아닌

포인터가 가리키는 type의 사이즈만큼

포인터 값을 증가시키라는 의미입니다.

실수라고 하기엔 너무 큰 무지군요 ㅎㅎ
이래서 게시판에서 이상한 답글 이야기가 나오는 거네요 ㅠ.ㅜ
ㅎㅎ 왜 그랬을까? 내가?

C++, 그리고 C++....
죽어도 C++

kuma의 이미지

캐스팅의 결과는 값입니다.

회사에서 인터넷 사용을 감시하는지라 길게 적지 못해 죄송합니다.

hwang의 이미지

((char *)pv)++
c 표준에서는 올바른 문법이 아니지만 c++에서는 표준에 맞습니다.
gcc에서는 c++과 동일한 식으로 동작합니다.

(char *)pv++
c, c++ 표준에서는 지원하지않은 형식입니다.
gcc 확장입니다. void *를 ++과같은 것을 만났을때 char *와 같이
취급해줍니다.

mr.hjkim의 이미지

C99에 보면 footnote 에 다음과 같은 부분이 있습니다.
A cast does not yield an lvalue.

casting을 다른 타입으로 하면 그 값이 lvalue가 되면 타입의 alignment라든지 type의 표현 방식과 같은 부분에 제약이 많이 생길겁니다.

위와 같은 표현에서 원래의 타입과 똑같은 char*로 변환을 했지만 그렇지 않고 alignment가 더 엄격한 타입으로 변환을 한다던지 하면 문제가 발생할 수 있습니다.

맞는 표현은 pv = (char*)pv + 1; 이 되겠지요

thyoo의 이미지

5.4 Explicit type conversion (cast notation) [expr.cast]

1 The result of the expression (T) cast-expression is of type T. The
result is an lvalue if T is a reference type, otherwise the result is
an rvalue. [Note: if T is a non-class type that is cv-qualified, the
cv-qualifiers are ignored when determining the type of the resulting
rvalue; see _basic.lval_. ]

C++ 참조형인 경우에만 L-value가 될 수 있다고 하는군요.

http://www.itga.com.au/~gnb/wp/cd2/index.html

((char*)pv)++와 (char*)pv++ 둘 다
VC7에서는 Compile Error가 발생합니다.

C++라면 ((char*&)pv)++로 하시면 됩니다.
C++라도 (char*&)pv++는 여전히 문제가 됩니다.
후위 인크리먼트가 먼저 호출되고 캐스트문이 실행 적용되기 때문에 인크리먼트에서 얼마를 증가시켜야 되는지 몰라 거기에서 에러를 발생시킵니다.

___________________________________
Less is More (Robert Browning)

죠커의 이미지

ixevexi wrote:
우선 포인터형의 크기는 모두 같은것 아닌가요?

동일한 환경도 동일하지 않는 환경도 있습니다.

pynoos의 이미지

CN wrote:
ixevexi wrote:
우선 포인터형의 크기는 모두 같은것 아닌가요?

동일한 환경도 동일하지 않는 환경도 있습니다.

혹시 과거의 far pointer 를 말씀하시는 것인가요?

yangam의 이미지

많이 배우네요.. 감사합니다

작은 것들, 사소한 것들을 소중히 여기고,
항상 최선을 다하는 멋진 사람이 되고 싶다.
그들이 나에게 일깨워준 것처럼,
그들 자신이 얼마나 소중한 존재인지 알 수 있도록
도와주는 그런 좋은 사람이 되고 싶다

댓글 달기

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