4
typedef struct mystruct{
  int a;
  char arr[10];
  char *str;
}mystruct;


void f(void *data, int offset){
  char *s = (char *)(data + offset);
  printf("%s", s);
}

void g(void *data, int offset){
  char *s = *(char **)(data+offset);
  printf("%s", s);
}

int main(){
  mystruct test;
  test.a = 2;
  test.str = malloc(100);
  strcpy(test.arr, "Hello ");
  strcpy(test.str, "World!");
  f(&test, offsetof(mystruct,arr));
  g(&test, offsetof(mystruct,str));
  return 0;
}

文字列を出力するために 2 つの異なる方法が必要なのはなぜだろうか。関数fで、(データ + オフセット) が実際に指しているのは何ですか? 文字列の最初の要素への char ポインターであるarrを指していませんか? しかし、関数gでは、 (data + offset) も char ポインターを指しています。では、同じタスクを実行するために 2 つの異なるアプローチを使用する必要があるのはなぜでしょうか?

4

5 に答える 5

3

どちらの場合も、 structdata+offsetのメンバーを指します。

しかし、構造体の構造を見てみましょう。それはで構成されています

+-----+--------------------------------------------+
| a   | sizeof(int) probably 4 or 8 bytes          |
+-----+--------------------------------------------+
| possible padding of unknown size (probably zero) |
+-----+--------------------------------------------+
| arr | 10 bytes                                   |
+-----+--------------------------------------------+
| possible padding of unknown size (maybe 2 bytes) |
+-----+--------------------------------------------+
| str | sizeof(char*) probably 4 or 8 bytes        |
+-----+--------------------------------------------+

メモリの他の場所には、 で割り当てられた 100 バイトのブロックがありますmalloc

のデータはに割り当てられたメモリにtest.arr格納さtestますが、 に格納されるtesttest.strはメモリの別のブロックのアドレスです。

于 2013-06-12T16:08:56.253 に答える
1

関数内にあるポインターのタイプに関するコンパイラー情報を提供する必要がfありg、void ポインターでポイント演算を行うことはできません。

datachar ポインターにキャストすると、printf が機能します。

void f(void *data, int offset){
  char *s = (char *)(( char*)data + offset); 
  printf("%s", s);
}

void g(void *data, int offset){
  char *s = *(char **)((char*)data+offset);   
  printf("%s", s);
}
于 2013-06-12T16:05:24.210 に答える
0

関数 f で、(データ + オフセット) が実際に指しているのは何ですか?

構造体オブジェクトの 'arr' メンバーを指しています (void ポインター演算に対する GCC のセマンティクスを想定している場合)。

文字列の最初の要素への char ポインターである arr を指していませんか?

arr は、char ポインターではなく、char 配列です。

しかし、関数 g では、(データ + オフセット) も char ポインターを指しています。

この場合、はい、char ポインターを指しています。

では、同じタスクを実行するために 2 つの異なるアプローチを使用する必要があるのはなぜでしょうか?

ポインターは 2 つの異なるものへのものです。1 つは char ポインター (それ自体が char 配列を指す) で、もう 1 つは char 配列です。最初のケースには、もう 1 レベルの間接化があります。

于 2013-06-12T16:19:17.163 に答える
0

あなたの構造体では、(おそらく) オフセット 4 は、「Hello」を構成する文字を含む 10 バイトのリストです。したがって、(data+4) は char へのポインターであり、それに応じてコード化する必要があります (つまりchar *)。

ただし、これらの 10 バイトの後に、バッファのアドレスをどこかにする数バイトが来ます。つまり、これらのバイトは 'char *' (定義したとおり) であるため、data+offset は char-pointer またはchar **。_

おそらく紛らわしいのは、両方の

strcpy(test.arr, "こんにちは");
strcpy(test.str, "ワールド!");

仕事。

これは紛らわしいです (ただし、C/C++ の便利な機能です)。配列要素の型へのポインターを必要とする場所で使用される場合、配列の名前は、配列の最初の要素へのポインターであるかのようにコンパイラによって処理されます。

test.str明らかに char へのポインターです (そのように定義したため) 。状況に応じて、test の最初の要素へのポインターとして使用test.arr できます。

strcpy(test.arr, "Hello "); コンパイラが想定している ことを書くと、strcpy(&test.arr[0], "Hello ");

于 2013-06-12T16:16:20.707 に答える