簡體   English   中英

通過指針訪問結構

[英]accessing struct by a pointer

我目前正在試驗指針,我對我的代碼有幾個問題

附: 這只是為了試驗我不會在任何代碼中使用它

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

struct obj
{
    int* IntPtr;
    obj()
    {
        IntPtr = new int[2];
        IntPtr[0] = 123;
        IntPtr[1] = 456;
    }
};

int main()
{
    obj MyStruct;
    long long int* Adress = (long long int*) & MyStruct; //pointer to a struct

    //change value in struct
    *(long long int*)(*Adress + sizeof(int)) = 789;

    std::cout << "get value by pointer: " << (int)*(long long int*)(*Adress + sizeof(int)) << std::endl; //std::cout crashes my program
    printf("get value by pointer: %d\n", (int)*(long long int*)(*Adress + sizeof(int)));
    printf("get value from struct: %d\n", MyStruct.IntPtr[1]);

    return 0;
}
  1. 為什么 std::cout 使我的程序崩潰? 我不得不使用 printf 函數來解決這個問題

  2. 我可以從我的主函數中刪除 IntPtr 嗎? 類似於delete[] (long long int*)*Adress; 然后創建新的? 喜歡:

    int* Itemp = new int[5]; *地址 = (long long int)Itemp;

編輯:這只是一個關於如何在strcut obj時訪問strcut obj int* IntPrt的實驗private:我不會使用其他方法。

即使帶有delete[]new的代碼在我的編譯器上也能正常工作

謝謝大家的解釋

即使您的代碼中的語法錯誤已修復,我懷疑您嘗試做的前提仍然存在根本性缺陷。 獲取一個指針,將其轉換為表示內存地址的數字,將其移動到另一個對象上並以這種方式訪問​​它,這在 C++ 中是不允許的。

允許編譯器並積極地基於程序從不做這樣的事情的假設來優化代碼。 因此,即使一個程序出現,而這樣做是工作,它可以在與不同的編譯器,不同的版本相同的編譯器,或者在相同的編譯器不同的編譯設置編譯很好的突破。

那么這對我們程序員來說意味着什么呢? 指針是內存地址並不意味着我們可以將它們視為內存地址(除了一些特定的例外)。

指針指向對象(提醒:即使是簡單的int也是一個對象)。 指針指向內存的事實是一個實現細節 除非您一次操作一個字節的底層存儲的原始字節。

您必須將指針視為:

  • 不指向對象,在這種情況下,您只能分配、復制或比較它。

  • 指向一個對象,在這種情況下,您也可以使用*->取消引用它。

  • 指向屬於數組一部分的對象,此時,您還可以使用[]或指針算術( +-等)來訪問同一數組中的其他對象。

就這樣。

考慮到這一點,您的代碼應該如下所示。 這主要是供參考。 我知道這不是你想要做的。

struct obj
{
    int* IntPtr;
    obj()
    {
        IntPtr = new int[2];
        IntPtr[0] = 123;
        IntPtr[1] = 456;
    }

    ~obj() 
    {
      // Btw. If you have a new, ALWAYS have a delete, even in throwaway code.
      delete IntPtr[];
    }
};

int main()
{
    obj MyStruct;
    
    // Get a pointer to the struct
    obj* Adress = &MyStruct;
 
    // Change value in struct via the pointer
    obj->IntPtr[1] = 789;
    (*obj).IntPtr[1] = 789;

    std::cout << "get value by pointer: " <<  obj->IntPtr[1] << std::endl; 
    printf("get value by pointer: %d\n", obj->IntPtr[1]);
    printf("get value from struct: %d\n", obj.IntPtr[1]);
}

編輯:為了完整起見,這里的代碼可以滿足我的解釋:

#include <iostream>
#include <cstdint>
#include <cassert>

struct obj {
    int IntData[2];
};

int main()
{
    obj MyStruct;

    // Get a number containing the memory address associated with MyStruct.
    // std::uintptr_t is the integer type of the same size as a pointer
    std::uintptr_t AdressOfMyStruct = (std::uintptr_t)&MyStruct;
    std::cout << "MyStruct lives at: " << AdressOfMyStruct << std::endl;

    // Do the same thing for IntData[1]
    std::uintptr_t AdressOfIntData1 = (std::uintptr_t)&MyStruct.IntData[1];
    std::cout << "MyStruct.IntData[1] lives at: " << AdressOfIntData1 << std::endl;

    // recalculate the address of IntData1 as an offset from MyStruct
    std::uintptr_t AdressOfIntData1Calculated = AdressOfMyStruct + sizeof(int);
    std::cout << "MyStruct.IntData[1] lives at (alt): " << AdressOfIntData1 << std::endl;

    // Verify that IntData[1] is where we expect it to be.
    assert( AdressOfIntData1Calculated == AdressOfIntData1 );

    // ...Everything up to here is valid code...

    // WARNING: this may looks like it works, but it is, in fact, Undefined Behavior.
    int* PtrToIntData1 = reinterpret_cast<int*>(AdressOfIntData1); 
    *PtrToIntData1 = 789;

    // WARNING: This is also undefined behavior.
    std::cout << "get value by pointer: " << *PtrToIntData1 << std::endl; 

    // This is fine, obviously.
    std::cout << "get value from struct: " << MyStruct.IntData[1] << std::endl; 

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM