【解決方法】[C] バイトアドレス範囲。

[ad_1]

こんにちは !

これがどのように機能するかを理解するのに苦労しています:

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

int main()
{
    int rows = 2;
    int columns = 5;
    int **matrix = (int **) malloc(rows * sizeof(int *));
    matrix[0] = (int *) malloc(rows * columns * sizeof(int));
    for (int i = 1; i < rows; i++)
    {
        matrix[i] = matrix[0] + i * columns;
        //printf("%p", *matrix[i]);
    }
     for (int i = 0; i < rows; i++)
    {
      
        printf("Indeks : %d, Address of (matrix) : %p\n", i, matrix+i);
        printf("Indeks : %d, Address of (*matrix) : %p\n", i, *(matrix+i));
    }
    
    return 0;
}

結果は次のようになります。

https://i.postimg.cc/FRZbkLLR/obraz-2023-10-18-050416732.png[^]

Indeks : 0, Address of (matrix) : 0x55eff083e2a0
Indeks : 0, Address of (*matrix) : 0x55eff083e2c0
Indeks : 1, Address of (matrix) : 0x55eff083e2a8
Indeks : 1, Address of (*matrix) : 0x55eff083e2d4

ここのようなチュートリアルから:

これは、行列のアドレスが4バイトごとに変更される必要があることを示していますが、コードでは8バイトごとに変更され、mallocを使用します。 しかし、*行列の場合、ifは4バイトごとに変化し、malloc「配列」でもあります。なぜ1つのmallocでは8バイトごとに変化し、他の4バイトでは両方ともintであり、int値は4バイトを必要とします。

それでは、私が行列 + 1 と書くとき、彼は私が 4 バイトを画像 604 にある別の数値に移動したいことをどのようにして知るのでしょうか。これは別の数値です。 両方のmallocがポインタである場合、彼はそれをどのように8バイトまたは4バイトに変換するのでしょうか(ポインタは8バイトかかると聞きましたが、(int*)mallocもポインタですが、8バイトではなく4バイトかかります)

または、文字を使用した別の例。

#include <stdio.h>

int main()
{
 
    char* arr[3] = { "geek", "Geeks", "Geeksfor" };
 
    for (int i = 0; i < 3; i++) {
        printf("Indeks : %d, Address of (arr) : %p\n",i , *(arr+i));
        printf("Indeks : %d, Address of (&arr) : %p\n",i , &arr[i]);
    }
 
    return 0;
}

結果 :

Indeks : 0, Address of (arr) : 0x55ae7f302008
Indeks : 0, Address of (&arr) : 0x7fff60e25ef0
Indeks : 1, Address of (arr) : 0x55ae7f30200d
Indeks : 1, Address of (&arr) : 0x7fff60e25ef8
Indeks : 2, Address of (arr) : 0x55ae7f302013
Indeks : 2, Address of (&arr) : 0x7fff60e25f00

ここでも、アドレス arr を見ると 4 バイト以上の差があります (文字が 4 つある場合、char には 1 バイトしかなく、論理的に 4 バイトかかります)。 ただし、&arr には 8 バイトがあります。 なぜ ?

char が 1 バイトであることを知っていて &arr + 1 を書くと、なぜ 8 バイトごとに書かれるのか意味がわかりません。
最初の例でも同じことが言えます。*matrix + 1と入力すると4バイトになることを理解するのに苦労していますが、matrix + 1と入力すると8バイトになります。両方のmallocアドレスがポインターであること、つまり、両方のmallocアドレスがポインターであることをどのようにして知るのでしょうか? 8バイトのアドレス

PS.
これらのバイトがどのように機能するのか、そして私が行列 + 1 を書き込むと 4 バイト進むことをどうやって彼が知るのか、私は非常に混乱しています。 char * arr がある場合、arr のアドレスはポインターでもある arr の内部へのポインターであり、このポインターは「G」のような値のアドレスを指しているため、ポインターへのポインターのようなものです。 したがって、2つのポインターがありますが、1つは文字ごとに1バイトであり、もう1つのポインターは1バイト前にありますが、ポインターのサイズは8バイトである必要があります…それがどのように機能し、そこで算術がどのように機能するのかがまったくわかりません。

私が試したこと:

算術について読んでみましたが、sizeof(int) または sizeof(int *) についてはある程度理解できましたが、まったく理解できません。 ポインタも4バイトまたは8バイトである必要があることも同様ですが、私の場合、ポインタは1文字あたり1バイトです…または、行列+ iなどの表記は理解できないかもしれませんが、行列のアドレスは理解していますsizeof で + i だけシフトされます。 行列の 2 つのアドレスの差は 8 バイトなので、+1 は 8 バイトずつシフトしますが、*(matrix+i) と書くと、*(matrix+0) と *(matrix+1) の差は 5 バイトだけです ( 4 文字 + \0 文字) もう一方の *(行列 +2) は 6 バイトの差です。

解決策 1

これに対する答えについては、前の質問で部分的にすでに述べました。

Indeks : 0, Address of (matrix) : 0x55eff083e2a0
Indeks : 0, Address of (*matrix) : 0x55eff083e2c0
Indeks : 1, Address of (matrix) : 0x55eff083e2a8
Indeks : 1, Address of (*matrix) : 0x55eff083e2d4

0x55eff083e2a8 – 0x55eff083e2a0 = 0x08
0x55eff083e2d4 – 0x55eff083e2c0 = 0x08

次の方法でポインタのサイズを確認できます。

printf("%d\n",sizeof(int*));
printf("%d\n",sizeof(int**));

次の例でも同じです:

0x7fff60e25f00 – 0x7fff60e25ef8 = 8
0x7fff60e25ef8 – 0x7fff60e25ef0 = 8

*(arr+1) として指定された値は無効です。ポインター型 0x55ae7f302013 のようなアドレスを持つことはできません。

ポインターの結果の長さが 6 バイトであるため、ここに投稿している内容の多くは、プログラムの実際の実行結果ではありません: 55 ae 7f 30 20 13 – これは印刷出力では不可能です。
「0x」プレフィックスは printf 関数に設定されていないため、次のようにする必要があります。 printf("Indeks : %d, Address of (arr) : 0x%p\n",i , *(arr+i)); その代わり。

そこで質問です。あなたは、質問しているコードを実行して、それがどのように機能するかを理解していますか?

解決策 2

ポインター演算ではポインターのサイズが使用されます。 したがって、ポインターがあり、それに 1 を加算すると、実際にはポインターのサイズが追加されます。32 ビット アプリケーションの場合は 4 バイト、64 ビットのアプリケーションの場合は 8 バイトです。 最後の例では、それぞれのポインターは arr コンパイラによって割り当てられた、メモリ内の固定 char 配列のアドレスを指します。 したがって、本質的には、 arr (ポインタの配列) は次のとおりです。

0 -> "geek\0"
5 -> "Geeks\0"
11 -> "Geeksfor\0"

しかし arr はポインタの配列であり、(2 行目に) 各ポインタのアドレス (すべて 8 バイト長) を出力しています。

[edit]

ここで図が役立つかもしれません。

--------------------------------------------
|g|e|e|k|\0|G|e|e|k|s|\0|G|e|e|k|s|f|o|r|\0|
--------------------------------------------
|0|1|2|3|4 |5|6|7|8|9 ...

つまり、それらのアドレスは [ 0, 5, 11 ] この図では有効なもののみです。 の住所 arr[0]arr[1] etc は、プーインターのアドレスを示しますが、それらが指すもの、つまりこれら 3 つの文字列は示しません。

[/edit]

[ad_2]

コメント

タイトルとURLをコピーしました