과거 C90버젼의 C로 작성된 소스는 현재의 VS2010 같은 컴파일러로 컴파일이 불가능한가요?

bshi02의 이미지

아래의 두소스는 아주 오래전에 유행했던 터보씨정복의 예제인데요 근데 보면 둘다 터보씨 전용함수를 전혀 사용하지 않았지만 컴파일하면

#include <stdio.h>
#define SMAX 11
#define NMAX 10
void arraycopy(void *dest,void *source,int size,int n);
 
void main()
{
	char s1[SMAX]="Good copy!";
	char s2[SMAX];
	int n1[NMAX]={000,100,200,300,400,500,600,700,800,900};
	int n2[NMAX];
	int i;
 
	arraycopy(s2,s1,sizeof(*s1),SMAX);
	arraycopy(n2,n1,sizeof(*n1),NMAX);
 
	printf("s1: %s\n",s1);
	printf("s2: %s\nn1",s2);
	for(i=0;i<NMAX;i++)
		printf("%03d ",n1[i]);
	printf("\nn2:");
	for(i=0;i<NMAX;i++)
		printf("%03d",n2[i]);
	printf("\n");
}
void arraycopy(void *dest,void *source,int size,int n)
{
	int register max;
 
	max=n*size;
	while(max-->0)
		*((char*)dest)++=*((char *)source)++;
}
 
 
//에러메세지
//32줄 IntelliSense: 식이 수정할 수 있는 lvalue여야 합니다.	
//32줄 error C2105: '++'에 l-value가 필요합니다.
 

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
 
#define printexprc(expr) printf("%16s==%c\n",#expr,expr)
#define printexprs(expr) printf("%16s==\"%s\"\n",#expr,expr)
#define printexpri(expr) printf("%16s==%d\n",#expr,expr)
 
void main(void)
{
	void *pv;
	char *ps,s[]="ABCDEFG";
int *px,x[]={1234,2345,3456};
ps=s;
px=x;
pv=ps;
 
printexprs(ps);
printexprs((char*) pv);
printexprc(*ps);
printexprc(*(char*)pv);
((char*)pv)++;
ps=pv;
printexprs((char*)pv);
printexprs(ps);
pv=px;
printexpri(*px);
printexpri(*(int*)pv);
printexpri(*(px+1));
printexpri(*((int*)pv+1));
printexpri(px[2]);
printexpri(((int*)pv)[2]);
}
 
//에러메세지
//22줄 error C2105: '++'에 l-value가 필요합니다.	
//23줄 error C2440: '=' : 'void *'에서 'char *'(으)로 변환할 수 없습니다.
//22줄 IntelliSense: 식이 수정할 수 있는 lvalue여야 합니다.	
//23줄 IntelliSense: "void *" 형식의 값을 "char *" 형식의 엔터티에 할당할 수 없습니다.	

에러가 나오는 데요. 근데 분명히 지금까지 터보씨정복 교재에 있는 소스를 컴파일 하면서 터보씨 전용 함수가 아니라면 vs2010에서 전부 문제없이 컴파일이 되었었는데 void포인터를 설명하고 있는 이 두 예제가 컴파일이 되지 않는데, 터보시 2.0은 C90으로 알고 있는데, 구체적으로 현재 표준과 어떤게 달라져서 위의 C90버젼의 예제들이 컴파일이 않되는 건지 알고 싶네요.

수정:몇번째줄에 에러가 있는지 쓰질 않아서 에러의 위치를 알수 없는 것 같아서 고쳤습니다.그리고 비쥬얼 스튜디오 2010 에서 컴파일 했습니다.

HDNua의 이미지

1. Visual Studio 2013 community 에디션에서 문제 없이 실행됩니다.
그런데 codepad.org와 ideone.com 온라인 컴파일러에서는 같은 오류가 발생하네요.

2. 이 코드에서는 다음과 같은 수식을 사용하지요.

(char*)pv++; // case 1
((char*)pv)++; // case 2

case 2와 같이 연산을 진행하면, 소괄호에 의해 pv에 캐스트 연산이 먼저 적용됩니다.
case 1의 경우 캐스트 연산보다 후위 연산자의 우선순위가 높아서,
++ 연산자가 먼저 계산된 후 캐스트 연산이 적용되는 것이구요.

TCPL에서는 부록 A7.5절에서, 캐스트가 있는 수식이 좌변값이 아니라고 설명하고 있습니다.
좌변값이란 할당 연산자(=, +=, ...)의 좌변에 올 수 있는 식을 말합니다.
예를 들어 int num;과 같이 변수가 정의되었다면 num = 10;에서 "num"은 좌변값이지만,
(int)num = 20;에서 "(int)num"은 좌변값이 될 수 없습니다.

이 오류는, 캐스트 연산이 먼저 적용되어 ((char *)pv) 수식이 좌변값이 아니게 된 상태에서
증감 연산을 사용하려고 했기 때문에 발생한 것으로 보입니다.
VS2013에서는 특수하게 처리하는지 컴파일이 되었습니다만.

현재 표준과의 차이는 잘 모르겠네요. 다른 분의 답변을 기다려봅니다.

3.
오류 메시지를 보여주실 때 몇 번째 행에서 오류가 났는지도 적어주시는 게 좋을 것 같습니다.

4.
(답변은 아니고, 다른 분들은 표준 문서에 이런 내용이 있어서 여기에 위반된다고 답변을 주시던데
그런 분들을 볼 때마다 뭔가 멋지다는 생각이 듭니다.)

저는 이렇게 생각했습니다.

bshi02의 이미지

답변 감사합니다. 결국 결국 캐스트 연산이 적용된 변수는 현재의 표준에서는 좌변값으로 허용하지 않은 것 같군요.

그리고 23번째 줄에서 "'void *'에서 'char *'(으)로 변환할 수 없습니다." 라고 에러가 나옵니다만
저 예제는 터보씨정복의 p639에 나오는데 본래는 char*,int*형의 포인터 변수를 void*형의 변수에 대입하거나 혹은 그 역으로 void*형의 포인터 변수를 char*,int*형의 변수에 대입하는 것이 가능하므로 void* 포인터변수는 양방향으로 대입하거나 대입받는 피연산자로 사용할 수 있다는 것을 보여주는 것으로 생각합니다만
그 이유는 모르겠습니다만 현재의 C 표준에서는 오로지 char*,int*형의 포인터 변수를 void*형의 변수에 대입하는 한방향만 가능 한 것 같네요.

댓글 달기

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