web-dev-qa-db-ja.com

C / C ++のsizeof char *配列

同様の問い合わせはたくさんありますが、私の場合、何が機能していないのかわかりません。

_int mysize = 0;
mysize = sizeof(samplestring) / sizeof(*samplestring);
std::cout << mysize << '\n' << samplestring;
_

これは出力します:

_4

Press 'q' to quit.
_

どのように可能ですか? 4は間違いなくこの文字列のサイズではありません。私も同じ結果で、以下を試しました:

mysize = sizeof(samplestring) / sizeof(samplestring[0]);

編集:OK、これは宣言です:

_char *samplestring = "Start."; 
_

C++を使用していますが、char *のみを受け入れる関数を使用する必要があります。コードの後半で、次のように新しい文字列をその変数に割り当てます。

_samplestring = "Press 'r' for red text.";
_

はい、コンパイラは警告を出しますが、上書きできない場合にどのようにして異なる文字列を使用できるかわかりません...

8
Abalieno

samplestringは文字列ではないため、_4_は文字列のサイズではありません。これは_char*_であり、そのサイズは(プラットフォーム上)4で除算され、1で除算されます(charのサイズ)は、正確には4です。

C++では、_std::string_とlength()メソッドを使用します。

Cでは、パラメーターとしてNULLで終了する文字ポインターを受け取るstrlenを使用します。

13
Luchian Grigore

まず、sizeof(samplestring[0])sizeof(*samplestring)と同じです。どちらもsamplestring配列の最初の要素のサイズを返します。そして、samplestringが文字の配列であると仮定すると、sizeof(char)は1として定義されます。

samplestringの宣言方法は示していません。次のいずれかになります。

_char const *samplestring = "Hello, World!";
_

または

_char *samplestring = malloc( ... );
_

または

_char samplestring[10];
_

最初の2つのケースでは、samplestringの型は_char *_であるため、sizeof(samplestring)sizeof(char *)を返します。これは、プラットフォームでは4です。

3番目のケースでは、samplestringの型は_char[10]_(10文字の配列)ですが、_char *_をパラメーターとして取る関数を呼び出すと、char配列は- decayは、配列の最初の要素を指すポインターを指します。この場合、関数内でsizeofを印刷しようとしても、ポインターのサイズが印刷されます。

元の配列のサイズを関数内から出力する場合は、関数のパラメーターを元の配列型へのポインターにする必要があります(型には元の配列のサイズが含まれます)。

_#include <stdio.h>

void foo( char (*arr)[42] )
{
  printf( "%u", (unsigned)sizeof(*arr) );
}

int main()
{
  char arr[42];
  foo( &arr );

  return 0;
}  
_

出力:

_42
_

これにより、関数に渡すことができる配列のサイズが修正され、多くの場合望ましくありません。他の唯一の解決策は、自分で配列を追跡することです(または、NULLで終了する文字列がある場合はstrlenを使用します)。

5
Praetorian

文字列を定数にする方法は2つあり、あなたのテクニックは最初の方法でのみ機能します。 1つ目はコンパイル時にサイズを取得できる文字の配列を作成し、もう1つは文字の配列にpointerを作成します。

char samplestring[] = "hello";
char * samplestring = "hello";

2番目のケースのサイズを実際の方法で取得しようとすると、ポインタのサイズがわかります。 32ビットのビルドでは、ポインタのサイズは4文字です。つまり、ポインタは4文字と同じ量のメモリを使用します。

以下はalwaysが正しくnullで終了する文字列の正しい長さを示しますが、遅くなります。

mysize = strlen(samplestring);
4
Mark Ransom

配列ではなくポインタがあるように見えます。プログラムが必要とする場合、配列はポインタに変換されるため、次のようになります。

_size_t size(char * p) { // p is a pointer
    return sizeof(p) / sizeof(*p); // size of pointer
}

size_t size(char p[]) { // p is also a pointer        
    return sizeof(p) / sizeof(*p); // size of pointer
}
_

ただし、sizeof (char) == 1なので、除算はここでは冗長です。ポインターがより大きな型を指している場合は、予期しない結果が得られます。

C++(ただしCではない)では、配列のサイズをテンプレートパラメータとして推定できます。

_template <typename T, size_t N>
size_t size(T (&)[N]) {
    return N;  // size of array
}
_

または、_std::vector_や_std::string_などのクラスを使用してサイズを追跡できます。

Cでは、strlenを使用してゼロで終了する文字列の長さを見つけることができますが、ほとんどの場合、配列のサイズを自分で追跡する必要があります。

1
Mike Seymour

あなたはcharのポインタのサイズを尋ねています。だからあなたは32ビットシステムを使っていると思います。

C++を使用している場合は、std :: stringを使用します。

std::string samplestring("Hello world");
std::cout << samplestring.size() << std::endl;
0

要素のsizeofは、そのオブジェクトに割り当てられたメモリのサイズを返します。あなたの例では、文字列はおそらくどこかで宣言されています

samplestring[4]

その場合、メモリのサイズは4です。アプリケーションでおそらく必要なメソッドは次のとおりです。

strlen(samplestring);

Nullで終了する文字列のサイズを返します(終了なし)

0
Minion91