2017-02-20 1 views
1

配列が空の場合、ARRAY_SIZEは未定義の動作を返しますか?我々はsizeof((X)[0])配列が空の場合、ARRAY_SIZEは未定義の動作を返しますか?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#ifndef ARRAY_SIZE 
#define ARRAY_SIZE(X) sizeof((X))/sizeof((X)[0]) 
#endif 

struct ka { 
    int a; 
    int b; 
}; 

int main(void) 
{ 
    struct ka k[] = {}; 
    printf("%d\n", ARRAY_SIZE(k)); 
} 
+4

これはC++ではありません。指定されていないバウンドの配列の場合、空の初期化子は禁止されています。 – mpiatek

+0

'sizeof(k [0])'は実際にはどのメモリにもアクセスしないので、これはUBではありません。これは 'sizeof(ka)'と全く同じです – rustyx

答えて

3

をunexistingのdevideを作るためには、標準CまたはC++でのゼロ・サイズの配列を持ってすることはできません。

あなたのコードは制約違反です(空のイニシャライザーリストはどこでも許可されていません)。

C++でもエラーです。 {}は、サイズを省略した配列定義では使用できません。 (C++ 14 [dcl.init.aggr]/4)

非標準のコンパイラ拡張を使用する場合、動作はその拡張の詳細によって異なります。

+0

gccを使ってビルドしてもCのエラーは返されません – MOHAMED

+2

なぜゼロで除算されるのですか? 'sizeof((X)[0])'は 'sizeof(struct ka)'であり、 '0'ではありません。 – mch

+1

@MOHAMED gccのデフォルトはGNU拡張モードです。C言語では '-std = c11 -pedantic'コンパイルスイッチを、標準的な動作を得るには' std = C++ 14 -pedantic'をC++に使用してください。 –

1

一般に、メモリアクセスの観点からは、sizeofのオペランドがVLAタイプでない限り、ではなく、と評価されます。したがって、この場合、x[0]は無効なメモリアクセスではありません。

C11、チャプタ§6.5.3.4、 発現またはタイプの括弧名前であってもよいsizeofオペレータは、オペランドのサイズ(バイト単位)をもたらす

強調鉱山、引用。サイズは、オペランドの のタイプから決定されます。結果は整数です。オペランドの型が可変長配列 型の場合、オペランドは評価されます。 それ以外の場合、オペランドは評価されず、結果は の整数定数です。

sizeof(arr)/sizeof(arr[10]); 

を書く

int arr[5]= {0}; 

のような配列のために広い意味で

、評価されていないにもarr[10]として有効あり、それが唯一のオペランドのサイズについてですの内容はではありません(したがって、逆参照は必要ありません)。前記

  • 長さゼロの配列は、それらがgcc extensionである、C標準ではありません。
  • sizeofは、サイズsize_tの結果を生成するので、結果を出力するには%zuフォーマット指定子を使用する必要があります。
+0

評価されていることは、それに関係しています –

+1

@ M.Mは無効なメモリを逆参照していますか? –

+0

ああ、私はx [0]が範囲外のアクセスになる可能性があると懸念していました。 –

関連する問題