今後,本連載で扱う予定の項目を以下に記します.
・GCC2.95から追加変更のあったオプションの補足と検証
・GCC2.95から追加変更のあった,その他言語仕様の補足と検証
・GDBを使用するためのデバッグオプションについての検証
・GCCが使用している標準ライブラリの使用法と検証
・GCCのプログラミング
・GTK,GNOME,KDEなどを使ったGUIプログラミング
その後,C++言語やProlog,Javaなども含めたプログラミング言語やスクリプト言語,またデータベースといった多種にわたるGNUツールに関して,解説および検証を行っていく予定です.
さて,GCC3.2.2になり,オプションの種類と使用法が変わってきました.それを2回の予定で説明・検証していきます.
■-ansi
ANSI規格に沿ったCプログラムをサポートします.つまり,ISO C89規格を採用しています.ここで,C99規格やGCCの拡張機能を使用するとエラーになります(リスト1).
〔リスト1〕C99規格でエラーになる例(test141.c)
|
/*
*可変個数の引数を持つマクロの例(C99規格)
*/
#include <stdio.h>
#define M_debug(format, ...) printf("debug:" format, __VA_ARGS__)
main()
{
int x01 = 100;
int x02 = 200;
M_debug("x01=%d\n",x01);
M_debug("(%d,%d)\n",x01,x02);
M_debug("(%d,%d,%d行目)\n",x01,x02,__LINE__ );
}
|
|
コンパイルした結果を以下に示します.
$ gcc -ansi -pedantic test141.c -o test141
$ test141.c:5:25: 警告: 無名可変引数マクロは C99 で採り入れられました
この場合,ワーニングエラーにはなりますが,実行は可能です.アセンブラソース(リスト2)も正しく展開されています.
〔リスト2〕生成されたアセンブラソース(test141_1.s)
|
.file "test141.c"
.section .rodata
.LC0:
.string "debug:x01=%d\n"
.LC1:
.string "debug:(%d,%d)\n"
.LC2:
.string "debug:(%d,%d,%d\271\324\314\334)\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $100, -4(%ebp)
movl $200, -8(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
subl $4, %esp
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC1
call printf
addl $16, %esp
pushl $12
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC2
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
以下に実行結果を示します.
$ ./test141
debug:x01=100
debug:(100,200)
debug:(100,200,12行目)
$
問題なく動作しました.また,デフォルトでコンパイルしても同じ実行結果になりました.
$ gcc test141.c -o test141
$ ./test141
debug:x01=100
debug:(100,200)
debug:(100,200,12行目)
$
■-std=
・指定するパラメータの値
c89
iso9899:1990
上の値を=の後に指定するとISO C89規格でコンパイルされます.現在は-ansiを指定したことと同義になります.
先に使用したソース(リスト1)をコンパイルすると,結果は以下のようになります.
$ gcc -std=c89 -pedantic test141.c -o test141
test141.c:5:25: 警告: 無名可変引数マクロは C99 で採り入れられました
$ gcc -std=iso9899:1990 -pedantic test141.c -o test141
test141.c:5:25: 警告: 無名可変引数マクロは C99 で採り入れられました
$
・指定するパラメータの値
c99
c9x
iso9899:1999
iso9899:199x
上の値を=の後に指定すると,ISO C99規格でコンパイルされます.前述したとおり完全にサポートしているわけではありません.
リスト1のソースをコンパイルすると,結果は以下のようになります.
$ gcc -std=c99 test141.c -o test141
test141.c:7: 警告: 戻り値の型をデフォルトの `int' とします
$ gcc -std=c9x test141.c -o test141
test141.c:7: 警告: 戻り値の型をデフォルトの `int' とします
$ gcc -std=iso9899:1999 test141.c -o test141
test141.c:7: 警告: 戻り値の型をデフォルトの `int' とします
$ gcc -std=iso9899:199x test141.c -o test141
test141.c:7: 警告: 戻り値の型をデフォルトの `int' とします
$
test141.cでは戻り値を明示的に指定していませんが,C99規格では許されません.そこでワーニングエラーを出します.
リスト3のアセンブラソースを見るとわかるように,デフォルトの戻り値を0として生成しています.
〔リスト3〕C99規格で生成されたアセンブラソース(test141_2.s)
|
.file "test141.c"
.section .rodata
.LC0:
.string "debug:x01=%d\n"
.LC1:
.string "debug:(%d,%d)\n"
.LC2:
.string "debug:(%d,%d,%d\271\324\314\334)\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $100, -4(%ebp)
movl $200, -8(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
subl $4, %esp
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC1
call printf
addl $16, %esp
pushl $12
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC2
call printf
addl $16, %esp
movl $0, %eax
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
・指定するパラメータの値
gnu89
上の値を=の後に指定すると,ISO C89規格とGCC拡張仕様の組み合わせ,かつC99規格を含む言語仕様となります.これが現バージョンのデフォルトです.
リスト1のソースをコンパイルすると,結果は次のようになります.
$ gcc -std=gnu89 test141.c -S
$ cp test141.s test141_3.s
$
リスト4のアセンブラソース,およびコンパイル結果を見ると-ansiでもC99規格でもないことがわかります.これがGCC独自の言語仕様です.
〔リスト4〕デフォルトの言語仕様で生成されたアセンブラソース(test141_3.s)
|
.file "test141.c"
.section .rodata
.LC0:
.string "debug:x01=%d\n"
.LC1:
.string "debug:(%d,%d)\n"
.LC2:
.string "debug:(%d,%d,%d\271\324\314\334)\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $100, -4(%ebp)
movl $200, -8(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
subl $4, %esp
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC1
call printf
addl $16, %esp
pushl $12
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC2
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
・指定するパラメータの値
gnu99
gnu9x
上の値を=の後に指定すると,ISO C99規格とGCC拡張仕様の組み合わせでコンパイルされます.将来は,これがデフォルトになります.
リスト1のソースをコンパイルすると,結果は以下のようになります.
$ gcc -std=gnu99 test141.c -S
test141.c:7: 警告: 戻り値の型をデフォルトの `int' とします
$ gcc -std=gnu9x test141.c -S
test141.c:7: 警告: 戻り値の型をデフォルトの `int' とします
$ cp test141.s test141_4.s
$
test141.cでは戻り値を明示的に指定していませんが,C99規格では許されません.そこでワーニングエラーを出します.
リスト5のアセンブラソースを見るとわかるように,デフォルトの戻り値を0として生成しています.つまり,C99規格を使用してコンパイルしています.
〔リスト5〕C99規格で生成されたアセンブラソース(test141_4.s)
|
.file "test141.c"
.section .rodata
.LC0:
.string "debug:x01=%d\n"
.LC1:
.string "debug:(%d,%d)\n"
.LC2:
.string "debug:(%d,%d,%d\271\324\314\334)\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $100, -4(%ebp)
movl $200, -8(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
subl $4, %esp
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC1
call printf
addl $16, %esp
pushl $12
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC2
call printf
addl $16, %esp
movl $0, %eax
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
では,リスト1のソースにGCC拡張機能を含む処理を追加して(リスト6),コンパイルしてみます.
〔リスト6〕C99規格およびGCC拡張機能を含む例(test142.c)
|
/*
*可変個数の引数を持つマクロの例(C99規格)
*typeofでマクロを作る例(GCC拡張規格)
*/
#include <stdio.h>
#define M_debug(format, ...)printf("debug:" format, __VA_ARGS__)
#define pointer(T) typeof(T *)
#define array(T, N) typeof(T [N])
main()
{
int ix;
int x01 = 100;
int x02 = 200;
/* */
array (pointer (char), 10) char_p;
array (pointer (long), 10) long_p;
/* */
M_debug("x01=%d\n",x01);
M_debug("(%d,%d)\n",x01,x02);
M_debug("(%d,%d,%d行目)\n",x01,x02,__LINE__ );
/* */
for (ix=0;ix<10;ix++)
{
char_p[ix] = (char *)'a'+ix;
long_p[ix] = (long *)(ix * 1000000L);
}
for (ix=0;ix<10;ix++)
{
printf("char_p[%d] = %d\n",ix,char_p[ix]);
}
for (ix=0;ix<10;ix++)
{
printf("long_p=[%d] = %d\n",ix,long_p[ix]);
}
}
|
|
$ gcc -std=gnu9x test142.c -o test142
test142.c:10: 警告: 戻り値の型をデフォルトの `int' とします
$ gcc -std=gnu9x test142.c -S
test142.c:10: 警告: 戻り値の型をデフォルトの `int' とします
$
両方の言語仕様を含むソースでも,問題なくコンパイルできます.では,実行してみましょう.
$ ./test142
debug:x01=100
debug:(100,200)
debug:(100,200,20行目)
char_p[0] = 97
char_p[1] = 98
char_p[2] = 99
char_p[3] = 100
char_p[4] = 101
char_p[5] = 102
char_p[6] = 103
char_p[7] = 104
char_p[8] = 105
char_p[9] = 106
long_p=[0] = 0
long_p=[1] = 1000000
long_p=[2] = 2000000
long_p=[3] = 3000000
long_p=[4] = 4000000
long_p=[5] = 5000000
long_p=[6] = 6000000
long_p=[7] = 7000000
long_p=[8] = 8000000
long_p=[9] = 9000000
結果とアセンブラソース(リスト7)を見ればわかるように,どちらの機能も生きています.
〔リスト7〕生成されたアセンブラソース(test142.s)
|
.file "test142.c"
.section .rodata
.LC0:
.string "debug:x01=%d\n"
.LC1:
.string "debug:(%d,%d)\n"
.LC2:
.string "debug:(%d,%d,%d\271\324\314\334)\n"
.LC3:
.string "char_p[%d] = %d\n"
.LC4:
.string "long_p=[%d] = %d\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $120, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $100, -16(%ebp)
movl $200, -20(%ebp)
subl $8, %esp
pushl -16(%ebp)
pushl $.LC0
call printf
addl $16, %esp
subl $4, %esp
pushl -20(%ebp)
pushl -16(%ebp)
pushl $.LC1
call printf
addl $16, %esp
pushl $20
pushl -20(%ebp)
pushl -16(%ebp)
pushl $.LC2
call printf
addl $16, %esp
movl $0, -12(%ebp)
.L2:
cmpl $9, -12(%ebp)
jle .L5
jmp .L3
.L5:
movl -12(%ebp), %edx
movl -12(%ebp), %eax
addl $97, %eax
movl %eax, -72(%ebp,%edx,4)
movl -12(%ebp), %ecx
movl -12(%ebp), %edx
movl %edx, %eax
sall $2, %eax
addl %edx, %eax
leal 0(,%eax,4), %edx
addl %edx, %eax
leal 0(,%eax,4), %edx
addl %edx, %eax
leal 0(,%eax,4), %edx
addl %edx, %eax
leal 0(,%eax,4), %edx
addl %edx, %eax
leal 0(,%eax,4), %edx
addl %edx, %eax
sall $6, %eax
movl %eax, -120(%ebp,%ecx,4)
leal -12(%ebp), %eax
incl (%eax)
jmp .L2
.L3:
movl $0, -12(%ebp)
.L6:
cmpl $9, -12(%ebp)
jle .L9
jmp .L7
.L9:
subl $4, %esp
movl -12(%ebp), %eax
pushl -72(%ebp,%eax,4)
pushl -12(%ebp)
pushl $.LC3
call printf
addl $16, %esp
leal -12(%ebp), %eax
incl (%eax)
jmp .L6
.L7:
movl $0, -12(%ebp)
.L10:
cmpl $9, -12(%ebp)
jle .L13
jmp .L11
.L13:
subl $4, %esp
movl -12(%ebp), %eax
pushl -120(%ebp,%eax,4)
pushl -12(%ebp)
pushl $.LC4
call printf
addl $16, %esp
leal -12(%ebp), %eax
incl (%eax)
jmp .L10
.L11:
movl $0, %eax
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
■-aux-info filename
ヘッダファイル中のものを含むすべてのプロトタイプ(リスト8)を出力します.
〔リスト8〕生成されたリスト(test142.txt)
|
/* compiled from: . */
/* /usr/include/libio.h:402:NC */ extern int __underflow (_IO_FILE *);
/* /usr/include/libio.h:403:NC */ extern int __uflow (_IO_FILE *);
/* /usr/include/libio.h:404:NC */ extern int __overflow (_IO_FILE *, int);
/* /usr/include/libio.h:405:NC */ extern wint_t __wunderflow (_IO_FILE *);
/* /usr/include/libio.h:406:NC */ extern wint_t __wuflow (_IO_FILE *);
/* /usr/include/libio.h:407:NC */ extern wint_t __woverflow (_IO_FILE *, wint_t);
/* /usr/include/libio.h:432:NC */ extern int _IO_getc (_IO_FILE *);
/* /usr/include/libio.h:433:NC */ extern int _IO_putc (int, _IO_FILE *);
/* /usr/include/libio.h:434:NC */ extern int _IO_feof (_IO_FILE *);
/* /usr/include/libio.h:435:NC */ extern int _IO_ferror (_IO_FILE *);
/* /usr/include/libio.h:437:NC */ extern int _IO_peekc_locked (_IO_FILE *);
/* /usr/include/libio.h:443:NC */ extern void _IO_flockfile (_IO_FILE *);
/* /usr/include/libio.h:444:NC */ extern void _IO_funlockfile (_IO_FILE *);
/* /usr/include/libio.h:445:NC */ extern int _IO_ftrylockfile (_IO_FILE *);
/* /usr/include/libio.h:463:NC */ extern int _IO_vfscanf (_IO_FILE *, const char *, __gnuc_va_list, int *);
/* /usr/include/libio.h:465:NC */ extern int _IO_vfprintf (_IO_FILE *, const char *, __gnuc_va_list);
/* /usr/include/libio.h:466:NC */ extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t);
/* /usr/include/libio.h:467:NC */ extern size_t _IO_sgetn (_IO_FILE *, void *, size_t);
/* /usr/include/libio.h:469:NC */ extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int);
/* /usr/include/libio.h:470:NC */ extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int);
/* /usr/include/libio.h:472:NC */ extern void _IO_free_backup_area (_IO_FILE *);
/* /usr/include/stdio.h:154:NC */ extern int remove (const char *);
/* /usr/include/stdio.h:156:NC */ extern int rename (const char *, const char *);
/* /usr/include/stdio.h:163:NC */ extern FILE *tmpfile (void);
/* /usr/include/stdio.h:173:NC */ extern char *tmpnam (char *);
/* /usr/include/stdio.h:183:NC */ extern char *tmpnam_r (char *);
/* /usr/include/stdio.h:196:NC */ extern char *tempnam (const char *, const char *);
/* /usr/include/stdio.h:202:NC */ extern int fclose (FILE *);
/* /usr/include/stdio.h:204:NC */ extern int fflush (FILE *);
/* /usr/include/stdio.h:209:NC */ extern int fflush_unlocked (FILE *);
/* /usr/include/stdio.h:222:NC */ extern FILE *fopen (const char *, const char *);
/* /usr/include/stdio.h:226:NC */ extern FILE *freopen (const char *, const char *, FILE *);
/* /usr/include/stdio.h:252:NC */ extern FILE *fdopen (int, const char *);
/* /usr/include/stdio.h:276:NC */ extern void setbuf (FILE *, char *);
/* /usr/include/stdio.h:281:NC */ extern int setvbuf (FILE *, char *, int, size_t);
/* /usr/include/stdio.h:288:NC */ extern void setbuffer (FILE *, char *, size_t);
/* /usr/include/stdio.h:291:NC */ extern void setlinebuf (FILE *);
/* /usr/include/stdio.h:298:NC */ extern int fprintf (FILE *, const char *, ...);
/* /usr/include/stdio.h:300:NC */ extern int printf (const char *, ...);
/* /usr/include/stdio.h:303:NC */ extern int sprintf (char *, const char *, ...);
/* /usr/include/stdio.h:307:NC */ extern int vfprintf (FILE *, const char *, __gnuc_va_list);
/* /usr/include/stdio.h:310:NC */ extern int vprintf (const char *, __gnuc_va_list);
/* /usr/include/stdio.h:313:NC */ extern int vsprintf (char *, const char *, __gnuc_va_list);
/* /usr/include/stdio.h:321:NC */ extern int snprintf (char *, size_t, const char *, ...);
/* /usr/include/stdio.h:325:NC */ extern int vsnprintf (char *, size_t, const char *, __gnuc_va_list);
/* /usr/include/stdio.h:354:NC */ extern int fscanf (FILE *, const char *, ...);
/* /usr/include/stdio.h:356:NC */ extern int scanf (const char *, ...);
/* /usr/include/stdio.h:359:NC */ extern int sscanf (const char *, const char *, ...);
/* /usr/include/stdio.h:383:NC */ extern int fgetc (FILE *);
/* /usr/include/stdio.h:384:NC */ extern int getc (FILE *);
/* /usr/include/stdio.h:387:NC */ extern int getchar (void);
/* /usr/include/stdio.h:396:NC */ extern int getc_unlocked (FILE *);
/* /usr/include/stdio.h:397:NC */ extern int getchar_unlocked (void);
/* /usr/include/stdio.h:402:NC */ extern int fgetc_unlocked (FILE *);
/* /usr/include/stdio.h:408:NC */ extern int fputc (int, FILE *);
/* /usr/include/stdio.h:409:NC */ extern int putc (int, FILE *);
/* /usr/include/stdio.h:412:NC */ extern int putchar (int);
/* /usr/include/stdio.h:421:NC */ extern int fputc_unlocked (int, FILE *);
/* /usr/include/stdio.h:426:NC */ extern int putc_unlocked (int, FILE *);
/* /usr/include/stdio.h:427:NC */ extern int putchar_unlocked (int);
/* /usr/include/stdio.h:433:NC */ extern int getw (FILE *);
/* /usr/include/stdio.h:436:NC */ extern int putw (int, FILE *);
/* /usr/include/stdio.h:443:NC */ extern char *fgets (char *, int, FILE *);
/* /usr/include/stdio.h:447:NC */ extern char *gets (char *);
/* /usr/include/stdio.h:480:NC */ extern int fputs (const char *, FILE *);
/* /usr/include/stdio.h:483:NC */ extern int puts (const char *);
/* /usr/include/stdio.h:487:NC */ extern int ungetc (int, FILE *);
/* /usr/include/stdio.h:492:NC */ extern size_t fread (void *, size_t, size_t, FILE *);
/* /usr/include/stdio.h:495:NC */ extern size_t fwrite (const void *, size_t, size_t, FILE *);
/* /usr/include/stdio.h:507:NC */ extern size_t fread_unlocked (void *, size_t, size_t, FILE *);
/* /usr/include/stdio.h:509:NC */ extern size_t fwrite_unlocked (const void *, size_t, size_t, FILE *);
/* /usr/include/stdio.h:515:NC */ extern int fseek (FILE *, long int, int);
/* /usr/include/stdio.h:517:NC */ extern long int ftell (FILE *);
/* /usr/include/stdio.h:519:NC */ extern void rewind (FILE *);
/* /usr/include/stdio.h:550:NC */ extern int fgetpos (FILE *, fpos_t *);
/* /usr/include/stdio.h:552:NC */ extern int fsetpos (FILE *, const fpos_t *);
/* /usr/include/stdio.h:577:NC */ extern void clearerr (FILE *);
/* /usr/include/stdio.h:579:NC */ extern int feof (FILE *);
/* /usr/include/stdio.h:581:NC */ extern int ferror (FILE *);
/* /usr/include/stdio.h:586:NC */ extern void clearerr_unlocked (FILE *);
/* /usr/include/stdio.h:587:NC */ extern int feof_unlocked (FILE *);
/* /usr/include/stdio.h:588:NC */ extern int ferror_unlocked (FILE *);
/* /usr/include/stdio.h:594:NC */ extern void perror (const char *);
/* /usr/include/stdio.h:606:NC */ extern int fileno (FILE *);
/* /usr/include/stdio.h:611:NC */ extern int fileno_unlocked (FILE *);
/* /usr/include/stdio.h:618:NC */ extern FILE *popen (const char *, const char *);
/* /usr/include/stdio.h:621:NC */ extern int pclose (FILE *);
/* /usr/include/stdio.h:627:NC */ extern char *ctermid (char *);
/* /usr/include/stdio.h:655:NC */ extern void flockfile (FILE *);
/* /usr/include/stdio.h:659:NC */ extern int ftrylockfile (FILE *);
/* /usr/include/stdio.h:662:NC */ extern void funlockfile (FILE *);
/* test142.c:10:OF */ extern int main (void); /* () */
|
|
$ gcc test142.c -aux-info test142.txt
■-fno-builtin,-fno-builtin-function
ライブラリ関数のうち,abort,abs,alloca,cos,exit,fabs,ffs,labs,memcmp,memcpy,sin,sqrt,strcmp,strcpy,strlenは効率を良くするために,組み込み関数としてコンパイルされることがあります.
その場合,デバッガを使用する際に意図しないふるまいをしたり,ライブラリ関数の処理自体が意図しないふるまいをすることがあります.それを防止するために「組み込みにしない」設定ができます.-fno-builtinは組み込み関数を,いっさい使用しません.
なお,以下に示すtest143.c(リスト9)とtest144.cは名前が違う同一のソースです.
〔リスト9〕組み込み関数を含む例(test143.c)
|
/*
*組み込み関数について
*/
#include <stdlib.h>
#include <stdio.h>
main()
{
int a;
a = abs(-5);
printf("%d\n",a);
}
|
|
$ gcc -fno-builtin test143.c -S
$ gcc test144.c -S
アセンブラソースを見ると,test143.s(リスト10)では,call absとなっていますが,test144.s(リスト11)では組み込み関数を呼び出しているようです.
〔リスト10〕test143.cから生成されたアセンブラソース(test143.s)
|
.file "test143.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
subl $12, %esp
pushl $-5
call abs
addl $16, %esp
movl %eax, -4(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
〔リスト11〕test144.cから生成されたアセンブラソース(test144.s)
|
.file "test144.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $5, -4(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
なお,-fno-builtin-functionというオプションもありますが,現バージョンでは何もしないことになっています.
以下に示すtest145.cとtest146.cは名前が違う同一のソースで,test143.cと同じです.
$ gcc -fno-builtin-function test145.c -S
$ gcc -fbuiltin-function test146.c -S
リスト12およびリスト13を見ればわかるように,どちらを指定しても組み込み関数を呼び出しています.
〔リスト12〕test145.cから生成されたアセンブラソース(test145.s)
|
.file "test145.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $5, -4(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
〔リスト13〕test146.cから生成されたアセンブラソース(test146.s)
|
.file "test146.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.align 2
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $5, -4(%ebp)
subl $8, %esp
pushl -4(%ebp)
pushl $.LC0
call printf
addl $16, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"
|
|
それは,リスト14,リスト15に示すシンボルリストでも確認できます.test143の場合,関数abs()は標準ライブラリ内のものをリンクしています.
〔リスト14〕test143.cから生成されたシンボルリスト(test143nm.txt)
|
080493ec D _DYNAMIC
080494c8 D _GLOBAL_OFFSET_TABLE_
080483d4 R _IO_stdin_used
w _Jv_RegisterClasses
080494b8 d __CTOR_END__
080494b4 d __CTOR_LIST__
080494c0 d __DTOR_END__
080494bc d __DTOR_LIST__
080493e8 d __EH_FRAME_BEGIN__
080493e8 d __FRAME_END__
080494c4 d __JCR_END__
080494c4 d __JCR_LIST__
080494e4 A __bss_start
080493dc D __data_start
08048390 t __do_global_ctors_aux
080482f0 t __do_global_dtors_aux
080493e0 d __dso_handle
w __gmon_start__
U __libc_start_main@@GLIBC_2.0
080494e4 A _edata
080494e8 A _end
080483b4 T _fini
080483d0 R _fp_hw
08048250 T _init
080482a8 T _start
U abs@@GLIBC_2.0
080482cc t call_gmon_start
080494e4 b completed.1
080493dc W data_start
0804832c t frame_dummy
08048358 T main
080493e4 d p.0
U printf@@GLIBC_2.0
|
|
〔リスト15〕test144.cから生成されたシンボルリスト(test144nm.txt)
|
080493b0 D _DYNAMIC
0804948c D _GLOBAL_OFFSET_TABLE_
08048398 R _IO_stdin_used
w _Jv_RegisterClasses
0804947c d __CTOR_END__
08049478 d __CTOR_LIST__
08049484 d __DTOR_END__
08049480 d __DTOR_LIST__
080493ac d __EH_FRAME_BEGIN__
080493ac d __FRAME_END__
08049488 d __JCR_END__
08049488 d __JCR_LIST__
080494a4 A __bss_start
080493a0 D __data_start
08048354 t __do_global_ctors_aux
080482c0 t __do_global_dtors_aux
080493a4 d __dso_handle
w __gmon_start__
U __libc_start_main@@GLIBC_2.0
080494a4 A _edata
080494a8 A _end
08048378 T _fini
08048394 R _fp_hw
08048230 T _init
08048278 T _start
0804829c t call_gmon_start
080494a4 b completed.1
080493a0 W data_start
080482fc t frame_dummy
08048328 T main
080493a8 d p.0
U printf@@GLIBC_2.0
|
|
■-no-integrated-cpp
GCCのサブプログラムには,cpp,cc1,as,ldがあります.そして,-Bオプションの指定でサブプログラムがどこにあるかを指定できます.つまり,指定の方法によっては標準でないcppを内部で実行することが可能になります.このオプションを指定すると,その機能を無視して標準のcppを使用します.なお,このオプションは将来も存続するかどうか不明だそうです.
標準でないcppを使う場合には,インストール時のカスタマイズで指定したほうが混乱しないでしょう.
|