2016-01-25 13 views
11

これを実行しようとすると、変数aの値が定数ではないというエラーが表示されます。私が明示的に変数aを定数にしたので、それは私には意味がありません。配列のサイズはそれよりも一定でなければなりませんか?意味は、#define a 5のみ、またはint arr[5]として初期化するか、malloc?私は何をしたのですか? Cにおいてconst intを使用して配列のサイズを定義する

int main{ 

    const int a = 5; 
    int i; 
    int arr [a]; 

    for (i = 0; i < 5; i++) { 
     arr[i] = i * 2; 
    } 

    printf("%d", arr[1]); 
    return 0; 
} 
+1

利用可能な代替案が主に '#define'または' malloc'であるとのあなたの仮定は正しい - それを修正するためにこれらの2つのオプションの1つを選んでください。 l3xの答えは、なぜその理由を説明する良い仕事です。 – GrandOpener

答えて

9

const読み取り専用をとして読まれるべきです。コンパイル時は定義しません。

6.7.9初期
4静的またはスレッドを持つオブジェクトの初期化子内のすべての式:

ここ
const int a = 5; 

aは、ないC standardによって必要とされる定数式であります記憶期間は定数 式または文字列リテラルでなければならない。

エラーは、C89/C90コンパイラを使用していることを示しています。ユーザーから入力されたaの入力を読み取って、variable length arrayと宣言することができます。これはC99機能で、自動保存期間があります。

#defineを使用することも別の方法です。しかし、それは単なるテキスト置換であり、自動記憶期間を持つ配列を定義します。 int arr[5];を自分で定義することと同じです。

ダイナミックストレージ(通常は「ヒープ」とも呼ばれます)にメモリを割り当てる場合は、malloc()ファミリーファンクションを使用する必要があります。このファンクションは、free()を呼び出すまでプログラムの実行中に有効です。

(この動作はconstです.C++はこれとは異なり、期待通りに動作します)。


私はC89でコードをコンパイルする場合、それはで失敗します(GCCもC89/C90でan extensionとしてそれをサポートしていますが)C89はのVLAをサポートしていないため

#include <stdio.h> 

int main(){ 

    const int a = 5; 
    int i; 
    int arr [a]; 

    for (i = 0; i < 5; i++) { 
     arr[i] = i * 2; 
    } 

    printf("%d", arr[1]); 
    return 0; 
} 

$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c 
test.c: In function âmainâ: 
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla] 
    int arr [a]; 
    ^

。したがって、C99をサポートしていないコンパイラを使用している場合は、VLAを使用することはできません。 たとえば、Visual StudioはC99およびC11のすべての機能を完全にサポートしていません。 Visual studio 2015 support most C99 featuresでも、VLAはその1つではありません。

しかし、同じコードが問題なくC99及びC11にコンパイル:

$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c 
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c 

可変長配列(のVLA)はC99で追加されたためにです。 VLAはC11標準でオプションになっていることに注意してください。したがって、実装はC11でVLAをサポートしない可能性があります。 実装でVLAがサポートされていないかどうかを確認するには、__STDC_NO_VLA__に対してテストする必要があります。

__STDC_NO_VLA__

6.10.8.3 Conditional feature macrosから意図1整数定数は、実装が可変長アレイまたは可変 改変タイプをサポートしていないことを示します。

配列サイズがかなり大きい場合、割り当ての失敗を移植可能に見つけることができないため、私は個人的にVLAを使用しません。例えば。

size_t size = 8*1024; 
int arr[size]; 

上記のフラグメントでは、arrの割り当てに失敗した場合、実行時まで認識できません。メモリの割り当てがプラットフォームに依存する「十分に小さい」サイズとは何ですか?したがって、1台のマシンでは、1MBの割り当てが成功する可能性があり、別のマシンでは失敗する可能性があり、さらに悪いことに、この失敗をキャッチする方法はありません。

したがって、VLAの使用は限られており、特定のプラットフォームで常に成功することがわかっている小型アレイでのみ使用できます。しかし、単に配列のサイズをハードコードして境界条件を処理するだけです。

+0

または、本当に配列サイズをハードコードしたい場合は、 'arraySize'という名前のディレクティブを使用してください。 – rlam12

+0

私はあなたがVLAへの参照を単に行った理由を理解していません。 OPは何をしようとしているのではないですか? MSVCを使用している場合でも、2015年版はVLAをサポートしていません。彼女はあなたの方法をその質問にも言及しているので、それをはっきりと理解しています。 –

+0

@WeatherVaneあなたはもう少し説明が必要です。私は更新をしました。ありがとう。 –

0

const - 修飾された変数は、定数式と同じではありません。定数式はコンパイル時にその値を知っていますが、const - 修飾された変数(通常は)はそうではありません。

C99以降では、可変長配列を宣言することができます。この場合、配列サイズは実行時まで分かりません。あなたは、C99以降のコンパイラを使用する必要があり、機能は2011標準でオプションなされたことを考えると、あなたはのVLAが利用できるかどうかを確認するための機能マクロをチェックする必要があります。少なくともまで非常に最近まで

static const int a = 10; // a is not a constant expression 

#if defined(__STDC__) && defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && !defined(__STDC_NO_VLA__) 
/** 
* VLAs are available in this environment 
*/ 
#define USE_VLA 1 
#endif 

#ifdef USE_VLA 
    int arr[a]; 
#else 
    /** 
    * VLAs are not available, either because it's a pre-1999 implementation, 
    * or it's a post-2011 implementation that does not support optional 
    * VLAs. We'll have to use dynamic memory allocation here, meaning we'll 
    * also need an explicit free call when we're done with arr 
    */ 
    int *arr = malloc(sizeof *arr * a); 
#endif 
... 
    do_something_interesting_with(a); 
... 
#ifndef USE_VLA 
    free(a); 
#endif 

MicrosoftのCコンパイラはVLAをサポートしていませんでした。ただし、宣言とコードが混在しているなど、C99の機能が追加されているため、最新バージョンではVLAがサポートされている可能性があります。知りません。

1

aの値を定義するためにenumを使用することがあります。

enum { a = 5 }; 
int arr [a]; 

は、おそらくこれは、列挙型の意思ではなく、列挙型のメンバーは#defineを使用して、すべてを定義する一般的な方法とは異なり、Cの定数に近いものです、aの可視性は範囲によって制限され、ここではarrと同じです。

+0

素晴らしいアイデア!!! – outoftime

関連する問題