Opensource.comは5月27日(米国時間)、「How to write a good C main function|Opensource.com」において、C言語の基本的な書き方、特にmain()を含むファイルの中身の構成を紹介した。

若者に人気の高いプログラミング言語はPythonとJavaScriptだと前置きした上で、C言語は多くの機能を備えた簡潔で有用なプログラミング言語であり、スピードが必要な場合はC言語が要求に答えてくれるかもしれないと説明している。

記事では、初めにmain()関数を含むC言語ファイルの基本的な構造を次のように紹介している。

/* main.c */
/* 0 コピーライト/ライセンス */
/* 1 #include */
/* 2 #define */
/* 3 extern */
/* 4 typedef */
/* 5 グローバル変数 */
/* 6 関数プロトタイプ */

int main(int argc, char *argv[]) {
/* 7 コマンド引数の解析 */
}

/* 8 関数 */

記事では各パートに関して説明を行っており、最終的にすべてをまとめたサンプルソースコードとして次のコードが掲載されている。

/* main.c - the complete listing */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>

#define OPTSTR "vi:o:f:h"
#define USAGE_FMT  "%s [-v] [-f hexflag] [-i inputfile] [-o outputfile] [-h]"
#define ERR_FOPEN_INPUT  "fopen(input, r)"
#define ERR_FOPEN_OUTPUT "fopen(output, w)"
#define ERR_DO_THE_NEEDFUL "do_the_needful blew up"
#define DEFAULT_PROGNAME "george"

extern int errno;
extern char *optarg;
extern int opterr, optind;

typedef struct {
  int           verbose;
  uint32_t      flags;
  FILE         *input;
  FILE         *output;
} options_t;

int dumb_global_variable = -11;

void usage(char *progname, int opt);
int  do_the_needful(options_t *options);

int main(int argc, char *argv[]) {
    int opt;
    options_t options = { 0, 0x0, stdin, stdout };

    opterr = 0;

    while ((opt = getopt(argc, argv, OPTSTR)) != EOF) 
       switch(opt) {
           case 'i':
              if (!(options.input = fopen(optarg, "r")) ){
                 perror(ERR_FOPEN_INPUT);
                 exit(EXIT_FAILURE);
                 /* NOTREACHED */
              }
              break;

           case 'o':
              if (!(options.output = fopen(optarg, "w")) ){
                 perror(ERR_FOPEN_OUTPUT);
                 exit(EXIT_FAILURE);
                 /* NOTREACHED */
              }    
              break;

           case 'f':
              options.flags = (uint32_t )strtoul(optarg, NULL, 16);
              break;

           case 'v':
              options.verbose += 1;
              break;

           case 'h':
           default:
              usage(basename(argv[0]), opt);
              /* NOTREACHED */
              break;
       }

    if (do_the_needful(&options) != EXIT_SUCCESS) {
       perror(ERR_DO_THE_NEEDFUL);
       exit(EXIT_FAILURE);
       /* NOTREACHED */
    }

    return EXIT_SUCCESS;
}

void usage(char *progname, int opt) {
   fprintf(stderr, USAGE_FMT, progname?progname:DEFAULT_PROGNAME);
   exit(EXIT_FAILURE);
   /* NOTREACHED */
}

int do_the_needful(options_t *options) {

   if (!options) {
     errno = EINVAL;
     return EXIT_FAILURE;
   }

   if (!options->input || !options->output) {
     errno = ENOENT;
     return EXIT_FAILURE;
   }

   /* XXX do needful stuff */

   return EXIT_SUCCESS;
}
  • main.c編集中サンプル

    main.c編集中サンプル

サンプルとして掲載されているソースコードはコンパイルして実行してもほとんど何もしてくれないが、C言語のソースコードを記述する上でのスケルトンとしては利用できるという。

記事では、コメントについてや引数のパース方法、返り値の使い方、関数プロトタイプと現在のコンパイラの実装、代表的なヘッダファイルなどの説明も掲載されている。