slide1 n.
Download
Skip this Video
Download Presentation
????? ???????

Loading in 2 Seconds...

play fullscreen
1 / 28

????? ??????? - PowerPoint PPT Presentation


  • 91 Views
  • Uploaded on

非標準機能 処理系依存機能. 内容. 非標準機能 標準化以前のソースコード 独自拡張 C99 と ISO C++ 処理系依存. 内容. 非標準機能 標準化以前のソースコード 独自拡張 C99 と ISO C++ 処理系依存. 標準化前のソースコード. C 言語 1990 年の標準化( C90 )と 1999 年の標準化( C99 )がある C++ 1998 年に ISO 標準策定( ISO C++, C++ std ). C 言語には 90 年以前に書かれたコード資産がある

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '????? ???????' - reed-lyons


Download Now An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2
内容
  • 非標準機能
    • 標準化以前のソースコード
    • 独自拡張
  • C99 と ISO C++
  • 処理系依存
slide3
内容
  • 非標準機能
    • 標準化以前のソースコード
    • 独自拡張
  • C99 と ISO C++
  • 処理系依存
slide4
標準化前のソースコード
  • C言語
    • 1990年の標準化(C90)と1999年の標準化(C99)がある
  • C++
    • 1998年にISO標準策定(ISO C++, C++ std)
  • C言語には90年以前に書かれたコード資産がある
  • Visual Studio 6.0 (コンパイラは 1997年のもの)で書かれたコードも多い

場合によっては、標準以前のコード→標準への変換が必要

slide5
関数の引数
  • 関数() と {} の間に引数の型を宣言

標準化前

C90

int function(arg1, arg2)

int arg1;

int arg2;

{

return arg1 + arg2;

}

int function(

int arg1,

int arg2)

{

return arg1 + arg2;

}

  • () 内で引数の型を宣言
for c
for 内で定義した変数(C++)
  • for の () 内で宣言した変数を、for ループの後ろで再利用可能

VC++ 6.0

ISO C++

for (int i=1; i<N; ++i)

sum += i;

for (i=1; i<N; ++i)

prod *= i;

for (int i=1; i<N; ++i)

sum += i;

for (int i=1; i<N; ++i)

prod *= i;

for (int i=1; i<N; ++i)

sum += i;

assert(i == N);

int i;

for (i=1; i<N; ++i)

sum += i;

assert(i == N);

  • for の () 内で宣言した変数は、for 内でしか使えない
slide7
std名前空間
  • .h なしのヘッダファイルも std 名前空間に入ってない

VC++ 6.0

ISO C++

#include <cstdio>

int main()

{

printf("foo\n");

}

#include <cstdio>

int main()

{

std::printf("foo\n");

}

  • .h なしのヘッダファイル中の関数は std 名前空間に入っている
slide8
内容
  • 非標準機能
    • 標準化以前のソースコード
    • 独自拡張
  • C99 と ISO C++
  • 処理系依存
slide9
独自拡張
  • たまにある誤解
    • 誤 : GCC でコンパイルできれば標準
    • 正 : GCCは独自拡張機能が多い
      • むしろ、標準対応率は VC++ 2005 のコンパイラが一番高い
  • GCC で C/C++ プログラムを書くときは、
  • -ansi -pedandic -std オプションを付ける
  • -ansi : C90, ISO C++(98) でコンパイル
  • -pedantic : GCC 独自拡張機能をオフにする
  • -std : -std "c++98" とかでバージョンを指定
slide10
配列のコピー代入
  • GCC では = で配列をコピーできる†
    • 標準では無理(ポインタ渡しなら可能)

char a[8], b[8]="StringB";

a = b;

  • 標準では・・・
    • memcpy を使う

char a[8], b[8]="StringB";

memcpy(a, b, 8);

†注意: 流石にこんなバグの原因になりそうな構文は、削除された模様。最新のGCCでは使えない。

switch case
switch case で範囲指定
  • GCC では、case に範囲を指定できる

switch (n) {

case 0 ... 3 : /* do something */break;

・・・

  • 標準では・・・
    • case を複数並べる

switch (n) {

case 0:

case 1:

case 2:

case 3:

/* do something */

break;

・・・

slide12
関数内で関数定義
  • GCC では、関数内に関数を書ける

void func(double x[], int num)

{

int inner(double xd) {

return 1 / (1 - xd);

}

for (int i=0 ; i<num ; i++) {

printf("%d\n", inner(x[i]));

}

}

  • 標準では同様の機能なし
slide13
内容
  • 非標準機能
    • 標準化以前のソースコード
    • 独自拡張
  • C99 と ISO C++
  • 処理系依存
c c99
C++とC99
  • C++とC99には互換性がない

C言語

C90

C99

互換性なし

上位互換あり

C++

ISO C++ (98)

  • C99 も標準とはいえ・・・
    • C++ との非互換が不評
    • 対応しているのは GCC くらい
      • 元々、GCC の独自拡張機能が C99 標準として採用された
c c991
C++とC99共通の機能
  • // コメント
  • inline キーワード
  • 暗黙の関数宣言廃止

C90

C99, C++

/* 戻り値・引数の型を省略

* すると int になる */

func(x1, x2)

{

return x1 * x2

}

// 型の省略禁止

// inline キーワード追加

inline

int func(int x1, int x2)

{

return x1 * x2

}

slide16
可変長引数マクロ
  • C99 では、可変長引数を持つマクロを定義できる

#define dbg(fmt, ...) \

printf("debug:" fmt, __VA_ARGS__)

  • C++ では・・・
    • 引数を持つマクロ自体非推奨
    • 代わりに inline 関数を使う

inline void dbg(char* fmt, ...)

{

va_list args;

va_start (args, format);

vfprintf (stdout, "debug:"format, args);

va_end (args);

}

slide17
可変長配列
  • C99 では、変数で配列の長さを指定できる

void func(int n)

{

double x[n];

・・・

  • C++ では・・・
    • 配列ではなく、vector クラスを使う

#include <vector>

using std::vector;

void func(int n)

{

vector<double> x = new vector<double>(n);

・・・

slide18
初期化子
  • C99 では、以下のような構文で構造体の初期化可能

struct point {

int x;

int y;

};

struct point p = { .x = 1, .y = 2};

  • C++ では・・・
    • コンストラクタを使う

struct Point {

int x;

int y;

Point(int xx, int yy) { x = xx; y = yy; }

};

Point p = new Point(1, 2);

restrict
restrict ポインタ
  • 二つのポインタが同じ箇所を指していないことを明示することでコンパイラの最適化を促す

void sumup(int n,

int * restrict array1,

int * restrict array2)

{

for (int i = 0; i < n; i++)array1[i] += array2[i];

}

  • こういう処理をするとき、array1 != array2 が保証されている場合にのみ使える命令があったりする
  • 残念ながら C++ には同様の機能なし
slide20
内容
  • 非標準機能
    • 標準化以前のソースコード
    • 独自拡張
  • C99 と ISO C++
  • 処理系依存
slide21
処理系依存
  • C/C++ の規格上、コンパイラごとに変えてもいい部分が多々ある
    • オペランドの評価順
    • short, int, long のサイズ
    • 構造体のパッキング
slide22
オペランドの評価順
  • a+b の a を先に評価するか b を先に評価するかは決められていない

int func(int n) {

printf("%d ", n); return n;

}

int x = func(1) + func(2);

  • 「1 2」と表示されるか「2 1」と表示されるかは未定義
  • ちゃんと分けて書くべき

int a = func(1);

int b = func(2);

int x = a + b;

short int long
short, int, long のサイズ
  • 規格上では、以下の不等号のみが定められている
    • sizeof(short) ≦ sizeof(int) ≦ sizeof(long)
  • short, int, long のサイズ
    • 16, 16, 32 ・・・ OK
    • 16, 32, 32 ・・・ OK
    • 16, 32, 64 ・・・ OK
    • 16, 64, 64 ・・・ OK
    • 32, 32, 16 ・・・ これは駄目
  • サイズ固定の整数を使いたければ・・・
    • int32 などを使う(コンパイラごとに異なる)
    • C99 には stdint.h という、サイズ固定の整数を定義したヘッダがある
slide24
構造体のパッキング(1)
  • 構造体のメンバとメンバの間には隙間が空くことがある
    • (例えば32ビットCPUでは)4バイト間隔でメンバがならんでいると効率よくアクセス可能
    • 隙間の空け方は規格で定められていない

struct {

char c1;

char c2;

} x;

long offset = &(x.c2) - &x;

  • offset の値は処理系ごとに異なる
slide25
構造体のパッキング(2)

struct {

char c1;

char c2;

} x;

以下の3つとも規格上 OK

x

x

x

c1

c1

c1

c2

c2

c2

  • コンパイラによっては、パッキング(メンバの並べ方)を指定可能(#pragma pack など。コンパイラごとに異なる)
slide26
コンパイラごとに処理を変える
  • コンパイラを判定
    • ifdef で各コンパイラ特有のシンボルを確認

#ifdef __GNUC__

// GCC 用コード

#endif

#ifdef __BORLANDC__

// Borland C++ 及び C++Builder 用コード

#endif

#ifdef __WATCOMC__

// Watcom C/C++ 用コード

#endif

#ifdef _MSC_VER

// Visual C++ 用コード

#endif

pragma
pragma
  • #pragma プリプロセッサ
    • コンパイラ依存の指示を出す
    • #pragma でできること / 書き方はコンパイラごとに異なる
    • 対応していない #pragma は無視する

(例) 構造体のパッキングを指定

#pragma pack(push,1)

struct {

char c1;

char c2;

} x;

  • 右の図のようになることが保証される
  • (この書き方は Visual C++ のもの)

x

c1

c2

slide28
参考URL
  • GCC 独自拡張
    • http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/gccextend.html
  • C99
    • http://seclan.dll.jp/c99d/c99d00.htm
  • VC++ 6.0 の癖
    • http://www.fides.dti.ne.jp/~oka-t/vc-mfc.html
ad