14583


ポインターはアドレス演算子で位置情報だけしか受け取っていないはずです。下のプログラムだとアドレスしか表示されません。

[code]

    cout<<&a;
    
[/code]

なのに、どうして終了する位置がわかるのですか


CC BY-SA 3.0
2015-08-18T02:16:40.123
14555
2015-09-08T22:54:02.140
2015-08-18T03:09:27.543
7831
10945
question
c++ c ポインタ
ポインター型はどうしてアドレスだけで情報が扱えるのですか


型情報があるからです。  
`int a`だとすると`&a`が示すアドレスから`sizeof(int)`バイトの領域までを値として扱います。


CC BY-SA 3.0
2015-08-18T02:24:52.583
14556
2015-08-18T02:24:52.583
7214
14555
answer


ポインタの指すものがどんな型なのか判明していれば、その長さもわかります。

[code]

    int a = 10;
    auto b = &a;
    cout << *b;
    
[/code]

この場合、コンパイル時に `&a` は `int` 型へのポインタ `int*` であることがわかるため、b も同様に `int*`
型と推論できます。それにより b の示す先は `sizeof(int)`
バイトだということがコンパイル時に確定し、ポインタの先から適切に値を取り出せるのです。

逆に、型が不明なポインタ `void*` や、配列へのポインタではデータの長さはわかりません。例えば文字列を `char`
の配列で渡す際には長さがわかりませんから、終端にヌル文字を入れることで文字列の終端がわかるようにしているのです。


CC BY-SA 3.0
2015-08-18T02:56:37.190
14559
2015-08-18T02:56:37.190
8000
14555
answer


既に回答があるとおり「コンパイル時に既知な型の範囲で」コンパイラは情報を引き出せます。  
コンパイル時にわからない内容は別途、実行時の処理が必要です。たとえば、

[code]

    struct base { virtual void ~base(); }; // 他にも polymorphic な関数があるとします
    struct derived1 : public base { ... }; // polymorphic な関数を実装してるつもり
    struct derived2 : public base { ... }; // derived1 とは内容が異なるつもり
    extern void func(base* p);
    void tester() {
        derived1 d1; func(&d1);
        derived2 d2; func(&d2);
    }
    
[/code]

のような場合 `func` に渡される引数の真の型が `derived1` か `derived2` かは  
`func` 自体にとっては実行するまでわからないわけです。

実際の機械語でも `func` の引数 `base*` 自体には「真の型」情報は入っていません。  
(ポインタの指す先つまりオブジェクト自体には「真の型」の情報が入っていますが)

コンパイラ的には、関数 `func` 内部では型 `base` は既知なので  
\- `base` にあるメンバ変数を使うことはできます  
\- `derived1` または `derived2` 固有のメンバ変数は使うことができません  
\- `base` 中の polymorphic な関数を呼ぶと真の型のメンバ関数が呼ばれます  
\- `base` になくて `derived1` にある polymorphic な関数は使うことができません  
(`derived1` からさらに派生して使う polymorphic 関数の意味)


CC BY-SA 3.0
2015-08-18T10:22:25.397
14583
2015-09-08T22:54:02.140
2015-09-08T22:54:02.140
10945
8589
14555
answer


これはコメントですが、`C++`のタグも正しいですか?`C`のネットワークの、メモリ境界をチェックしないために使える以下のコードの質問に思えてなりません

[code]

    struct icmp = *icmp;
    char buff[8+1000];
    // 何かしらの処理
    icmp = buff;
    
[/code]

実行できるプログラムだと以下のCのコードがあります。

[code]

    #include<stdio.h>
    #include<stdint.h>
    
    int main(int argc, char** argv)
    {
        struct aa{
            uint8_t x[4];
        };
    
        struct aa *hog;
    
        uint32_t buf = 1214849280;
        hog=&buf;
        //処理系のエンディアンに合わせて出力
        int x=1;
        if (*(char*)&x) {
            printf("%c%c%c%c\n",(char)hog->x[3],(char)hog->x[2],(char)hog->x[1],(char)hog->x[0]);
        }else{
            printf("%c%c%c%c\n",(char)hog->x[0],(char)hog->x[1],(char)hog->x[2],(char)hog->x[3]);
        }
    
    }
    
[/code]


CC BY-SA 3.0
2015-08-19T07:27:01.147
14618
2015-08-19T07:27:01.147
10972
14555
answer