4 に答える
これは私が期待または意図したものではありません。なぜなら、最終的に、関数は function(unsigned char *bytes) {... を使用したかのように動作するからです。
あなたの意見はまったく正しいです。Cでの記述は、関数のパラメーター リストでの記述unsigned char bytes[1024]
とまったく同じです。unsigned char *bytes
まったく同じように機能し、動作します。
しかし、関数のパラメーター内でその制限を明示的に事前定義する方法はありませんか?
C にはありません。できることは、固定サイズの配列を持つ構造体を定義することです。
typedef struct {
unsigned char buffer[1024];
} arraytype;
次に、関数パラメーターの型として使用できるarraytype *
ため、コンパイラーは、実際の関数呼び出しが適切に型指定されたarraytype *
ポインターを使用することを確認します。もちろん、そのままのunsigned char
配列を渡すことはできません。使用する必要がありますarraytype
。
配列は関数内のポインターに分解され、配列サイズも次のように渡します。
function(unsigned char bytes[], unsigned int bytelen)
式に現れる array-of-T 型の左辺値は (3 つの例外を除いて) 最初の要素へのポインターに崩壊します。結果のポインターの型は T へのポインターです。
(例外は、配列が sizeof または & 演算子のオペランドであるか、文字配列のリテラル文字列初期化子である場合です。)
C では、N 個の配列は N 個の連続したストレージのチャンクです。設計上、それ以上に洗練されたものではありません。したがって、s
が 1024 文字の配列の先頭を指している場合、1023 個、または 256 個、または 3 個の配列の先頭も指しています。And s+1
、s+400
and s+768
(または&s[1]
、&s[400]
and &s[768]
、正確に同等) も、256 個の配列の先頭を指します。
いずれにせよ、コンパイラがこのようなものをチェックする可能性はほとんどありませんが、チェックする可能性はあります。
正確に 256 文字のオブジェクトについて議論したい場合は、それを構造体にラップします。
struct TwoFiveSix {
char s[256];
};
関数のプロトタイプが a のアドレスを取ると言っている場合、struct TwoFiveSix
別のものを渡そうとすると、コンパイラは間違いなく文句を言います。ひもみたいな。
どのように関数を呼び出していますか? 次のようなものを想像してください。
void f()
{
const char* p = get_a_line_from_file();
function(p);
}
実行時にファイルに大量のデータが含まれていると仮定するとget_a_line_from_file()
、文字列が 256 文字になるかどうかをコンパイラがコンパイル時に知る方法は明らかにありません。
一方では...
char local_buffer[256];
populate(local_buffer, sizeof local_buffer);
function(local_buffer);
...コンパイラがコンパイル時にローカルバッファサイズを確認することは可能です。それが必要な場合は、次のように、関数が呼び出される前にそうする必要があります。
#define FUNCTION(X) do { STATIC_ASSERT(sizeof local_buffer == 256); function_impl(x); } while (false)
これは、囲まれた式が静的に true であると判断されない場合にエラーを生成するサポート マクロ STATIC_ASSERT を想定しています。間違いなく、オンラインで多くの適切な実装を見つけることができます。do
-イディオムは、マクロが-句内のwhile
単一行ステートメントとして適切に機能することを保証するために、マクロで一般的に使用されます。if
else
これに関する問題は、バッファがローカルでない場合、次のように実装を直接呼び出すことにフォールバックする必要があることです。
void g(const char* p)
{
function_impl(p);
}
void h()
{
char local_buffer[256];
g(local_buffer);
}
全体として、コンパイル時の検証を行う価値はほとんどありません。
コンテンツが ASCIIZ / NUL で区切られている場合は、実行時のstrlen()
検証が必要になる可能性があります。
(C++ では、 を使用してこれを確認できますtemplate <size_t N> void function(const char (¶m)[N]) { ... }
)