함수 선언에 대한 질문을 드립니다.(ex: reply(n, fmt, p0, p1, p2, p3, p4, p5))

anaud2의 이미지

안녕하세요
업무상 참고하는 소스에서 함수 선언이 처음보는 함수의 선언이라 질문을 드리겠습니다.
ex)=========================================
reply(n, fmt, p0, p1, p2, p3, p4, p5)
char *p0, *p1, *p2, *p3, *p4, *p5;
int n;
char *fmt;
{
printf("%d ", n);
printf(fmt, p0, p1, p2, p3, p4, p5);
printf("\r\n");
(void)fflush(stdout);
if (debug) {
syslog(LOG_DEBUG, "<--- %d ", n);
syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5);
}
}
===========================================
이렇게 되어 있습니다. 연습용으로 똑같은 방식의 선언으로 함수를 만들었을때도 결과는 같습니다.
그런데 여기서 문제가 위의 방식으로 printf()을 사용하듯이 사용을 합니다. 어떤말이냐면
reply(220,"test 입니다.")
reply(220,"test 내용은[%s]",ex1);
reply(220,"test no[%d],[%s]",intex1,ex1);
이런식으로 계속 사용이 되고 있습니다.

윗분의 말에 따르면 저렇게 인자의 갯수가 맞지않게 전달을 한다면 문제가 발생할수 있다 바꾸어라
라고 합니다.
그러나 소스는 정상적으로 판매가 이루어졌던 소스이고 저부분 때문에 현재 죽는프로그램이 해결이 될거 같지 않고
또 저부분을 막았는데도 죽는문제는 해결이 안되었습니다.

처음 사용하는 함수 선언이라...pritnf처럼 인자의 갯수가 유동성이 생기는지 잘모르겠네요 위와같은 선언이 유동성이 생기는 부분이라면 그대로
쓰고 싶은데 ..

위와 같이 선언이 되는부분은 어떤것일까요 답변을 부탁드립니다~

chadr의 이미지

위의 함수 선언은 좀 오래된 방식의 함수선언입니다.

http://kldp.org/node/34511#comment-106067

이곳을 참고해보세요.

저게 버그의 원인은 아닙니다만 앞으로 나오는 컴파일러에서는 컴파일이 안될수도 있습니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

grassman의 이미지

다음과 같은 가정을 한다면 프로그램이 segment fault를 내며 죽을 수 있습니다.

1. 운영체제에서 access violation을 처리해줌
2. reply 함수의 format 설정과 실제 전달된 인자의 개수가 다를 경우

위의 두 조건이 만족되면 access violation과 함께 프로그램이 죽을 수 있습니다.

그리고 reply 함수의 인자 개수에 대한 컴파일러의 경고가 있었을 것으로 보입니다만...
가변 인자로 사용하려면 va_arg 등의 함수를 사용하여 처리하는 것이 좋을 것으로 생각됩니다.

상용 프로그램에서 사용하기에는 좀 적절하지 않은 코드라고 볼 수 있을 것 같습니다.

cppig1995의 이미지

pre-ANSI C 방식입니다. 함수 원형(prototype)의 도입과 함께 저 방식은 사라졌습니다.
저 함수를 표준형으로 다시 머리만 작성하면 다음과 같이 됩니다.
int reply(int n, char *fmt, char *p0, char *p1, char *p2, char *p3, char *p4, char *p5);
그러나 여전히 가변 개수 인자에 대해 잘못된 점이 있기 때문에, 저런 코드를 사용하면 안 됩니다.
(http://cinsk.org/cfaqs/html/node17.html#15.12를 참고하십시오.)
정상적인(표준) 가변 개수 인자 함수는 다음과 같이 짭니다 (그냥 예제입니다):

#include <stdarg.h>
#include <stdio.h>
 
int fprint_chars(FILE *out, ...)
{
	va_list argp;	// 가변 개수 인자 목록(variable-length arguments list) 선언
	int i;	// 문자를 저장하기 위한 임시 변수
	va_start(argp, out);	// 탐색 시작
	while(i = va_arg(argp, int)) putchar(i);	// int 인자를 받는다.
		// int를 받는 이유는 정확한 원형(prototype)이 제공되지 않은 함수에 대해서는
		// 자동으로 진급(promotion)이 다음과 같이 적용되기 때문이다:
		// char, signed char, unsigned char, short int, unsigned short int -> int, float -> double
	va_end(argp);	// 탐색 종료
	return 0;
}
 
int main(void)
{
	fprint_chars(stdout, 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', 0);
}

한편, 위의 reply 함수를 표준에 맞게 짜면 다음과 같이 됩니다.

void reply(int n, char *fmt, ...)
{
	va_list argp;
	printf("%d ", n);
	va_start(argp, fmt);
	vprintf(fmt, argp);
	va_end(argp);
	printf("\r\n");
	fflush(stdout);
	if(debug)
	{
		syslog(LOG_DEBUG, "<--- %d ", n);
		va_start(argp, fmt);
		vsyslog(LOG_DEBUG, fmt, argp);
		va_end(argp);
	}
}

고전적인 syslog 인터페이스에 대해 시스템에서 가변 개수 인자 목록을 받는 변형 vsyslog를 제공한다고 가정하였습니다.


한말글 프로그래밍 언어 "열정" http://me-lang.wo.tc

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

anaud2의 이미지

정말 많은 도움이 됐습니다.

vsyslog의 말씀은 무슨 뜻이진 몰라서 man페이지를 찾아봤었을때 syslog페이지가 나오면서 제일 마지막에
syslog와 같은 동작을 한다라는 뜻으로 해석이 되어서 그대로 사용을 했었습니다.

통상적으로 함수를 사용을 할때는 main문 전에 선언을 해놓거나 프로토타입의 함수를 선언을 해줘야한다고
알고 있었는데 위에 제가 물어봤던 예전 선언방식에서는 main문 밑에 선언을 해서 사용이 가능한가봐요

수정을 하고나서 main문 위에 프로토타입을 선언해줘야 오류가 나질 않았습니다.
va_list
va_start
va_end
va_arg는 몰랐는데 좀더 공부해봐야겠습니다. 도움 너무 감사드리며 공부 앞으로 더 열심히 하겠습니다.

댓글 달기

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