[완료] C 덕분에 요새 다시 머리가 아프군요.

winner의 이미지

char charr[5][5];
const char (*pcarr)[5] = charr;

밑의 줄이 호환되지 않는 변환이 되더군요.
혹시나 해서

const char (* const pcarr)[5] = charr;

을 해보았습니다만 마찬가지입니다.

이에 대한 적절한 해석부탁드립니다.

1년 전에 작성한 code 를 다시 분석하다가 마주친 녀석입니다.

loser의 이미지

C에서는 pointer to const char과 pointer to char이 호환이 안되는 듯 하더군요.
어떤 type이 있을 때
type과 const type은 호환이 되지만
pointer to type과 pointer to const type은
안되는듯 합니다.
배열이나 volatile이 붙을 경우에도 마찬가지.

위에줄에서 charr을
array of array of char로 선언했으니까
아래줄의 charr은
pointer to array of char이 될 테고
pcharr은
pointer to array of const char
당근 호환 안되죠

const char (* const pcarr)[5] = charr;
의 경우에도
pcarr은
const pointer to array of const char이 될 테니까
여전히 호환이 안되겠네요.

해결책은
char (* const pcarr)[5] = charr;
이렇게 하면
charr은
pointer to array of char
pcarr은
const pointer to array of char
type과 const type은 호환되니까 OK.
다만 pcarr자체는 const니까 차후 변경이 안되겠네요.
pcarr로 배열에 접근해서 수정하는건 가능해도.

type qualifier는 타입명의 맨 앞에 붙었을때만
서로 호환이 됩니다.
pointer나 array, structure등을 통해
중간에 붙었을 때는
호환되지 않습니다.

winner의 이미지

제가 원했던 것은 pcarr 을 통해서 배열 member 를 수정할 수 없도록 하기 위함이었는데요.
적절한 대안이 없는 것 같군요.

이중 pointer 에 대한 형한정어가 변환에 미치는 영향은 어찌어찌 이해가 갑니다만
이것은 또 왜이러는지...~

이것이 안되는 이유가 논리적 문제점을 가지고 있어서인지, 아니면 기술적 한계인지 설명해줄 수는 없을까요?

loser의 이미지

저도 야매로 대충 배워서 왜 두개가 서로 호환형이 아닌지에 대해 설명드리진 못하겠습니다.
compatible type란 개념에 대해 대충 넘어가서;;;

하지만 무조건 되게 해야하는 거라면 해결책은 제시할 수 있습니다.

char charr[5][5];
void * t = charr;
const char (*pcarr)[5] = t;

말씀하신 대로의 목적 뿐이라면
두 타입 간에 정렬제한 문제가 발생하거나
혹은 const인 객체를 수정하거나 하는 일은 없을 듯하니
아마도... 아마도 별 문제 없을 것 같습니다.

문제 생기면 저 찾지 마세요;;;

winner의 이미지

void * 로 변환후 원래의 형과 호환되지 않는 형으로 돌아오지 않는 것은
표준에 보장되지 않는 방식으로 압니다.
그런 식으로 compiler 의 경고와 오류를 피해갈 바엔 아예 casting 을 하거나
경고가 나는 상태로 쓰는게 나을 것 같습니다.

익명 사용자의 이미지

: C에서는 pointer to const char과 pointer to char이 호환이 안되는 듯 하더군요.

여기에 대해서 다른 분들께 추가설명이 필요할 것 같군요.

표준의 Conversions -> Pointers 중에 이런 설명이 있습니다.

For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to
the q-qualified version of the type; the values stored in the original and converted pointers
shall compare equal.

pointer to const char 에서 pointer to char 로의 변환은 가능한데 그 역은 안됩니다.

두 타입이 서로 compatible type이 아닐꺼라고 생각은 하지만,
확신은 못하겠고 왜 그런지도 설명은 못드리겠습니다.

제가 C언어의 type에 대한 이해가 변변찮아서 좀 횡설수설합니다. 이해 바랍니다.

winner의 이미지

그러니까 char * 에서 const char * 로의 변환은 가능합니다.
표준의 내용도 그런 이야기이구요.

제 관심은 char (*)[상수] 에서 const char (*)[상수] 가 가능한지를 묻고 있습니다.

즉 pointer to basic type 에서 pointer to const basic type 은 분명 변환이 되지만
basic type 이 아닌 배열이 올 경우 어떻게 되는지가 궁금하네요.
만일 basic type 이 아닌 pointer 가 올 경우 문제가 있을 수 있다는 점은 알고 있습니다.

다시 말해
char ** 에서 const char ** 는 불가능하죠.
pointer to pointer to basic type 에서 pointer to pointer to const basic type 은 불가능하다는 뜻입니다.

harisoo의 이미지

char charr[5][5];
const char (*pcarr)[5] ={charr[0],charr[1],charr[2],charr[3],charr[4]};

포인터배열이므로 구성원은 포인터가 되어야 할 듯합니다.

const char (*pcarr)[5] = charr;
이것은 포인터배열에 더블포인터를 assign한것이니 호환이 안되겟죠

loser의 이미지

님이 올린 코드 컴파일해서 확인부터 해보십시오.
winner님이 어설픈 문제갖고 질문올리겠습니까?

님은 복잡한 선언의 해석방법부터 잘못 익히셨습니다.
아니, 그 이전에 배열과 포인터부터 다시 공부하셔야 할 듯 합니다.
이번을 기회로 해서 기초부터 다시 복습하십시오.

winner의 이미지

다만 저 역시 그다지 대단한 문제를 올린 것은 아닙니다.
harisoo 씨의 글은 과거 저를 떠올리는 부분이 많구요.
예전에 저는 훨씬 졸렬한 글을 올린 적도 많습니다.
검색해보면 많이 나오죠.

답변이 좀 강렬해서 저를 생각해주시는 것은 감사합니다만 반대로 부담감도 조금 오는군요. ^_^

익명 사용자의 이미지

char charr[5][5];
const char (*pcarr)[5] = charr;

위 두줄은 VS.Net 2005와 gcc 4.1.2에서 에러없이 정상동작합니다.

컴파일 환경을 알려주실수 있나요?

winner의 이미지

Ubuntu 7.04 에 포함된 gcc 4.1.2 와 MinGW 5.1.3 에 포함된 gcc 3.4.2 로 compile 을 했습니다.
물론 compile 은 됩니다만 warning 이 나오죠.

형변환에 좀더 딱딱한 C++ 로 compile 하면 아예 error 가 나죠.

익명 사용자의 이미지

그런가요?
이상하네요. C++에선 깨끗이 컴파일될 텐데요.
따라서 static_cast도 필요없고요.
질문하신 분은 아마 C++로 컴파일하신 듯합니다.

winner의 이미지

error 는 다른 곳에서 난 것이었습니다.
두줄 warning 이 났었는데 C++ 로 바꾸자 똑같이 비호환 변환 문제로
error 가 두 줄이 나와 제가 성급하게 판단했었네요.

fox9의 이미지

캐스팅 해서 변환하면 되지 않나요?

const char (*pcarr)[5] = (const char (*)[5])charr;

winner의 이미지

Casting 은 표준이 보장하는 바를 넘어서는 강력한 programmer 의 의지를 보여주는 것이니까요.
C++ 의 경우 static_cast 를 쓰게 되면 어떻게 될지 궁금하군요...

jg의 이미지

g++ 로 컴파일하면 위의 코드는 워닝/에러가 나지 않았습니다.
잘못 컴파일 한 건가요? (gcc에서는 워닝 뜹니다.)

댓글 첨부 파일: 
첨부파일 크기
Image icon 2007-08-07-192557_497x257_scrot.png80.13 KB

$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}

winner의 이미지

Compiler 최신이군요. Early adapter 들은 부럽습니다. ^_^

winner의 이미지

gcc 의 문제일까요?... ^_^

jg의 이미지

추측에 불과하지만
gcc는 “아마 문제가 될 것이다.” 로 대충 넘어가고
g++는 “문제 있어보이는데.. 더 살펴봤더니 아니다.” 로 짚고 넘어가는게 아닐까요? =_=;;

$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}

winner의 이미지

Compiler 의 품질일 뿐 표준의 요구사항은 아닙니다만...

gcc 의 message 는 다음과 같습니다.
warning: passing arg 1 of `함수이름' from incompatible pointer type

may 라는 단어만 넣어줬어도 제가 의심하지는 않을텐데 말이죠.

익명 사용자의 이미지

int main()
{
char charr[5][5];
char (*pcarr)[5] = charr;

pcarr[0][0] = 20;

printf("%d\n", charr[0][0]);

return 0;
}
ubuntu 7.04
gcc는 4.02입니다..
shell: gcc -W -Wall -o test test.c
./test 결과 20입니다;; 문제 없는 코드 아닌가요..(전 const는 안썻지만요..)
(warning도 없습니다.)

익명 사용자의 이미지

아무리 생각해도 const 때문에 뜨는 warning 같은데요 -_-++

익명 사용자의 이미지

운영자님 밑에 글 2개 지워 주세요 -_-++
부탁드립니다;;

익명 사용자의 이미지

const 때문에 에러 나는거 아닌가요;;

익명 사용자의 이미지

const 때문에 나는 warning가 아니면 warning가 안날꺼 같은데요..

익명 사용자의 이미지

winner 님 메일 주소가 어떻게 되시죠?
메일 드리려 했는데 사용자 정보에 메일 주소가 공개되어 있지 않네요... --;

winner의 이미지

winner at uos ac kr 입니다.
서울시립대 대학원생입니다...
그런데 대게 어떻게 써야 spammer 들한테 안 걸리죠?

익명 사용자의 이미지

메일 보냈습니다.

흠... 메일 주소는... 글쎄요... 저 같은 경우 그냥 @ 정도만 at 으로
대체해 공개하고 스팸은 필터링에 의존하고 있습니다. 필터링 통과하는
스팸 몇개는 재미삼아 봐주고 있습니다. ^^

좋은 하루 되세요~

winner의 이미지

익명사용자 분의 e-mail 로 제 궁금증의 대부분이 해결되었습니다.
그럼 다들 즐프~

익명 사용자의 이미지

그 답변이 저도 궁금한데 공개하실 생각 없으세요?
특별히 숨길 이유가 없다면요.

익명 사용자의 이미지

아마도 winner님께 메일을 보낸 사람은
몇몇 유저들이 kldp에서 쫓아낸 그 사람일테고
kldp를 끊겠다는 자신의 맹세를 지키는 것이겠죠.
따라서 이메일 내용이 공개될일은 없겠군요.

저도 내용이 몹시 궁금하긴 합니다만
이메일 내용이 공개되는 일은 없었으면 합니다.
있을때는 박대하더니만 없으니 또 아쉬워들 하는군요.

아마 이메일 내용이 그대로 올라오면
이 쓰레드는 또다시 길고도 복잡한 가지치기를 하게 될 것입니다.

길고도 장황한 설명이 될게 뻔하니
거기에 달리는 답변은 분명
말장난을 통한 주제 흐리기나 글쓰는 스타일에 대한 공격,
혹은 de facto standard 떡밥이 되겠죠.
늘 그랬으니까.

그 사건을 계기로 다른 사람들도 대부분 KLDP의 분위기를 파악하고
잠수를 탄 듯 싶습니다.
누군가가 해답을 제시해 줄 법한 문제인데도
모두들 입을 굳게 닫고 있습니다.

굳이 아쉬우신 분은 winner님께 직접 이메일을 보내 질문해 보시는 것이 어떻습니까?

winner의 이미지

알고 있던 내용이었습니다. pointer 를 반복적으로 적용하는 과정에서 const 가 어떤 영향을 주는가하는
문제는 익히 아는 내용이었습니다만 이를 배열에 적용할 때 어떻게 될 것인가가 제 의문이었습니다.

하지만 C compilier 가 표준에 의거하여 char ** 를 const char ** 로 변환을 거절하는 것과
char (*)[상수] 를 const char(*)[상수] 를 거절하는 것은 동일한 과정을 통해서 이루어진다고 합니다.

댓글 달기

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