• ベストアンサー

Cの関数定義で見慣れない記述がありました

libeventというソフトのソースに以下のような関数定義がありました。 この関数の定義部分が見慣れないものでした。 この関数は、size_tを戻り値としてもち、_event_strlcpyという名前で、 引数として、dst, src, sizの三つをもつというのはわかるのですが、 どうして_event_strlcpy(dst, src, siz)のように、 引数に型が宣言されていないのでしょうか?こういう書き方はアリなのですか? 普通は、_event_strlcpy(char *dst, const char *src, size_t size) というように書くものではないでしょうか? しかも、_event_strlcpy(dst, src, siz)の次の行からの、 char *dst;const char *src;size_t size;の三行は何なのでしょうか? このような位置にこういった書き方をするのはアリなのですか? size_t _event_strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ }

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

> _event_strlcpy(dst, src, siz) > char *dst; > const char *src; > size_t siz; は、いわゆる分離形式というやつで、標準化以前のCはこの記法しかできませんでした。標準化に際して、C++流の関数原型を兼ねた一括形式が取り入れられ、現在ではそれが主流になっています。なお、標準化以降も(現行規格であるC99でも)分離形式は使用可能です。 なお、このソースはおそらく標準化以降のものだと思います。あるいは、標準規格に完全準拠ではない過渡期の処理系にあわせたものかも知れません。 というのも、const修飾子も標準化の際にC++から取り入れた仕様ですので、昔のCにはなかったからです。

toshiaki33
質問者

お礼

遅くなりました。すみません。 なるほど、ありがとうございます。 質問のコードはlibeventというモジュールのソースで見かけたものでした。

その他の回答 (4)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★Tacosan さんへ。 ・回答 No.2 で試したのですがワーニングのほかにコンパイルエラーになってしまったので。  いろいろ試したら strcpy 関数名を変えたらコンパイル出来ました。  『string.h』はインクルードしていないのでコンパイルできるかと思いましたがエラーに  なっていたようです。 ●質問者さんへ。 ・C ソースでコンパイルすれば多少の警告は出るもののコンパイルできました。  回答 No.2 の関数名を適当に別名にすれば出来ました。 ・以上。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

や~, 今の C でもオプションで指定しない限りエラーにしちゃまずいでしょう>#1 一応, ISO C でも認められてるんだし. C++ ならエラーにしていいけど.

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★追記。 ・次のリンクをどうぞ。  http://forums.belution.com/ja/vc/000/343/00s.shtml→『関数宣言と定義で引数型が異なる場合のコンパイルエラーの発生方法について』  『K&R』の旧式スタイルは VC++2003 ではワーニングが出てエラーにもなりました。 旧スタイルの例: char *strcpy( dst, src ) char *dst; const char *src; {  char *head = dst;    while ( (*dst++ = *src++) != '\0' ){   ;  }  return head; } 以上。

参考URL:
http://forums.belution.com/ja/vc/000/343/00s.shtml
toshiaki33
質問者

お礼

K&Rの古いスタイルですか。ありがとうございます。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★『K&R』時代の古いソースだよ。 ・ANSI C 言語以前の記述はそのような感じでした。  つまり  char *strcpy( dst, src )  char *dst;  char *src;  {    :   省略    :   return dest;  }  という書き方です。 >このような位置にこういった書き方をするのはアリなのですか?  ↑  今の新しいコンパイラではワーニングとか、エラーになりませんか?  古いコンパイラなら問題ないとは思いますが相当古いコンパイラですよ。 ・以前、MS-DOS 時代に MSC Ver.4.0~Ver.6.0 を使っていましたが Ver.4.0 は  古い『K&R』の記述法でも問題なくコンパイルできた気がします。 ・以上。参考に。→ANSI C 以前の記述です。

toshiaki33
質問者

お礼

cygwinでgccでコンパイルしたら問題なくとおりました。 ありがとうございました。

関連するQ&A

  • CからC#へ

    C#2008を使っています。 以下の昔のソースをC#に置き換える場合、引数のconst部分などでエラーが表示されます。 どのようにすればよいのでしょうか? int check(const char* s) { char msg[256]; // 正しいサイズか short siz = strlen(s); if(64 != siz){ sprintf(msg, "sが64バイトではありません。siz=[%d] s=[%s]\n", siz, s); printf("%s", msg); return 0; } // 正常 return !0; }

  • 関数がうまく動作しない

    関数get_monthにchar *型の文字列を引数にして、先頭の三文字(大文字でも小文字でも可)が正しいかどうかを関数strnxcmpでチェックしていくものです。 ところが、関数get_month中のreturn iで帰ってくるのはメインプログラムを動作させたところいつも0になってしまっているようです。(本当は1~12が帰ってくるようにしたい。) for(i=1;i<=12;i++) { if(strnxcmp(tuki[i],s,3)==0) { return i;←ここのリターンで0が帰ってきてしまう。 } } } 何がおかしいためにこのようになってしまうのでしょうか? よろしくお願いします。 int strnxcmp(const char *s1,const char *s2,size_t n) { while(n && toupper(*s1) && toupper(*s2)) { if(toupper(*s1) != toupper(*s2)) { return ((unsigned char)*s1 - (unsigned char)*s2); } s1++; s2++; n--; } if(!n)return 0; if(*s1) return 1; return -1; } int get_month(char *s) { int m,i; char *tuki[]={"","January","Feburary","March","April","May","June","July","Augst", "September","October","November","December"}; for(i=1;i<=12;i++) { if(strnxcmp(tuki[i],s,3)==0) { return i; } } return -1; }

  • c言語関数の(1)~(5)までの部分が何をやっているのかよく分からない

    c言語関数の(1)~(5)までの部分が何をやっているのかよく分からないので、どなたか解説をお願いします。 int memcmp(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = (const unsigned char *)s1; const unsigned char *p2 = (const unsigned char *)s2; while (n-- > 0) { if (*p1 != *p2) return (*p1 - *p2); p1++; p2++; } return (0); } return (*p1 - *p2); > (1) ---------------------------------------------------------------------- char *strcat(char *s1, const char *s2) { char *p = s1; while (*s1) s1++; /* s1を末尾まで進める */ while (*s1++ = *s2++) ; /* '\0'が見つかるまでs2をコピー */ return (p); } while (*s1++ = *s2++) ; > (2) ---------------------------------------------------------------------- char *strstr(const char *s1, const char *s2) { const char *p1 = s1; const char *p2 = s2; while (*p1 && *p2) { if (*p1 == *p2) { p1++; p2++; } else { p1 -= p2 - s2 - 1; p2 = s2; } } return (*p2 ? NULL : (char *)(p1 - (p2 - s2))); } while (*p1 && *p2) > (3) p1 -= p2 - s2 - 1; > (4) ---------------------------------------------------------------------- char *strcpy(char *s1, const char *s2) { char *p = s1; while (*s1++ = *s2++) ; return (p); } while (*s1++ = *s2++)   > (5) ;          > (5) ----------------------------------------------------------------------

  • 文章中から特定の文字列を抜き出すプログラムについて C言語

    log.txtの文章からIPを抜き出しip.txtに書き込むというものです。log.txtの文章は基本的にfrom IP:port の順です。しかし文章中にfromがないとip.txtで空欄になってしまいます。 例192.168.1.100  192.168.1.110 理想はfromがない行はなにも追加せず次に移りたいのですがどうすればいいでしょうか? 例192.168.1.120 192.168.1.130 192.168.1.140 void addLine(const char*,FILE*); char *getFromIP(const char*,char*); int main() { FILE *pFileA = fopen("log.txt","rt"); char buff[256]; if(pFileA){ FILE *pFileB = fopen("ip.txt","wt"); if(pFileB){ for(;fgets(buff,256,pFileA) != NULL;){ char buff2[32] = {'\0'}; addLine(getFromIP(buff,buff2),pFileB); } fclose(pFileB); } fclose(pFileA); } return 0; } char *getFromIP(const char *line, char *buff) {  char *src, *dst;        src = strstr(line, "from");  if(src==NULL) { return buff; }   src += 4;            dst = buff;          while(1) {   if(isspace(*src))  {    src++;    continue;          }   else break;         }                    while(1) {   *dst = *src;          if(*dst == ':')        {    *dst = '\0';          break;           }   if(*dst == '\0')       {   break;           }  dst++;            src++;           }  return buff;         } void addLine(const char *str,FILE *pFile){ char buff[1024]; sprintf(buff,"%s\n",str); fputs(buff,pFile); }

  • C++の関数テンプレートで分からないところがあります。

    C++の関数テンプレートで分からないところがあります。 C++の入門書を読んで勉強しているのですが、その演習問題(答えはついてないです)で、以下のような問題がありました。 ----------------------------------------------------- 配列の全要素の最小値を求める関数テンプレートを作成せよ。 teplate <class Type> Type minof(const Type x[], int n); という形で作ること。 なお、最も小さい文字列を求められるようにするために、const char *型に明示的に特殊化したものも合わせて作成すること。 ------------------------------------------------ という問題なのですが、これにたいして僕は以下のように答えました。ヘッダのインクルードなどは省きます。 template<class Type> Type minof(const Type x[], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(x[min] < x[i])             min = i;     return x[min]; } template<> const char* minof<const char *>(const char x[][64], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(strcmp(x[min], x[i]) < 0)             min = i;     return x[min]; } int main() {     const int n = 5;     int a[n];     char s[n][64];     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> a[i];     }     cout << "文字列\n";     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> s[i];     }     cout << "整数の最小値---" << minof(a, n) << "です\n";     cout << "文字列の最小値---" << minof<const char *>(s, n) << "です\n"; } これをコンパイルすると、エラーで 明示的な特殊化; 'const char *minof<const char*>(const char [][64],const int)' は関数テンプレートの特殊化ではありません と 'minof' : 1 番目の引数を 'char [5][64]' から 'const char *const []' に変換できません。 とでてしまいます。 色々探してみたのですが、解決できませんでした・・。 特に最初のほうのエラーがよくわかりません。ちゃんと特殊化してる気はするのですが・・。 間違っている箇所の正当を載せていただけるとわかりやすくて、ありがたいです。 よろしくお願いします!

  • C言語の標準関数の引数の順番について

    C言語標準関数の引数についての質問です。 strcpy、memsetなど C言語の標準関数の引数に注目したところ 前に出力パラメータを持ってきているものが多いように思えます。 例えば、 char *strcpy(char *dest, const char *src); の場合、 第1引数の"dest"が出力パラメータで 第2引数の"src"が入力パラメータとなっています。 入力よりも出力を前に持ってきている理由が何かあるのでしょうか。 今後、自分が設計をするときの参考にしたいと考えているので 理由を知っている方がいたら教えて下さい。

  • プログラミングカテゴリ見つかりませんでした…C言語

    プログラミングカテゴリ見つかりませんでした…C言語勉強中なのですが…参考書の以下の書き方がよくわかりません。 int strncomp(const char *s1,const char *s2,size_t n) このsize_tってどういう意味なのでしょうか? 教えていただけると助かります

  • strcpy関数について(\0のコピー)

    '\0'のsrcからdstへのコピーについて考えて見たのですが、 char *strcpy(char *dst,const char *src) { int i=0; for(i=0;src[i]!='\0';i++) dst[i]=src[i]; dst[i]=src[i];←1 return dest; } このプログラムではfor文の真偽値の判定の段階では'\0'がsrcからdstにコピーできていないので1のdst[i]=src[i]でコピーする必要がありますが、以下のようにプログラムを変更すると char *strcpy(char *dst,const char *src) { int i=0; for(i=0;(dst[i]=src[i])!='\0';i++) ; return dest; } (dst[i]=src[i)の代入式の段階でsrcからdstにコピーしその後でfor文の真偽値の判定をするので、真偽値判定前にdst側配列に'\0'が入っていると言う考えでこのプログラムを理解して良いのでしょうか。なにかミスしそうなプログラムですが、考え方として、私の言っている事は正しいでしょうか。宜しく回答願います。

  • bsearch関数の内容について

    stdlib関数のbsearch関数で、次のことを教えてください。 void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { size_t pl = 0; /* 探索範囲先頭の添字 */ size_t pr = nmemb - 1;/* 探索範囲末尾の添字 */ char *x = (char *)base;/*なぜchar *にキャスト?*/ if (nmemb > 0) { while (1) { size_t pc = (pl + pr) / 2;/* 探索範囲中央の添字 */ int comp = compar((const void *)&x[pc * size], key); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ /*なぜsizeを掛けるのか?*/ if (comp == 0) /* 探索成功 */ return (&x[pc * size]); else if (pl == pr) break; else if (comp < 0) pl = pc + 1;/* 探索範囲を後半に絞り込む */ else pr = pc - 1;/* 探索範囲を前半に絞り込む */ } } return (NULL);/* 探索失敗 */ }

  • c言語 iconv

    msys環境で実行して,指定されたファイルの文字コードをShift-JISに変換して表示するコードを作成しているのですがうまく表示されません.何がいけないのでしょうか.第1引数に変換対象のファイル名,第2引数にファイルの文字コードを指定しています. #include <stdio.h> #include <string.h> #include <iconv.h> int main(int argc, char *argv[]) { iconv_t conv; char src[10000]; char dst[10000]; int src_len = strlen(src); int dst_len = sizeof(dst) - 1; char *buf_in; char *buf_out; FILE *fp; fp = fopen(argv[1], "r"); if(NULL == fp) { printf("ファイルを開けません\n"); } else { while(fgets(src, 10000, fp) != NULL) { buf_in = src; buf_out = dst; /* 変換器を作成 */ conv = iconv_open("Shift-JIS", argv[2]); /* 変換 */ iconv(conv, &buf_in, &src_len, &buf_out, &dst_len); *buf_out = '\0'; /* 終末処理 */ /* 文字コード後の文字列を表示 */ printf("%s\n", dst); } /* 変換器を終了 */ iconv_close(conv); /*ファイルを閉じる*/ fclose(fp); } return 0; }

専門家に質問してみよう