欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

計算機(jī)內(nèi)存探秘:物理存儲器、地址空間與內(nèi)存地址

 更新時間:2025年05月24日 14:26:09   作者:web安全工具庫  
程序和數(shù)據(jù)放在內(nèi)存里運(yùn)行,聽說過“內(nèi)存地址”這個詞,但它到底代表什么?物理內(nèi)存條、顯卡顯存、主板上的ROM...這些都是存儲器,它們是如何被統(tǒng)一管理的?本文將帶你探索計算機(jī)存儲器的不同層面,理解物理存儲器、存儲地址空間以及程序所感知的“內(nèi)存地址”之間的關(guān)系

對于初學(xué)者來說,計算機(jī)的“內(nèi)存”概念有時會讓人感到困惑。我們知道程序和數(shù)據(jù)放在內(nèi)存里運(yùn)行,也聽說過“內(nèi)存地址”這個詞,但它到底代表什么?物理內(nèi)存條、顯卡顯存、主板上的ROM...這些都是存儲器,它們是如何被統(tǒng)一管理的?

本文將帶你探索計算機(jī)存儲器的不同層面,理解物理存儲器、存儲地址空間以及程序所感知的“內(nèi)存地址”之間的關(guān)系。

1. 物理存儲器:硬件層面的“倉庫”

首先,我們來談?wù)?strong>物理存儲器 (Physical Storage)。顧名思義,這是指計算機(jī)硬件中實(shí)際存在的、用于存儲數(shù)據(jù)的芯片或設(shè)備。最常見的物理存儲器包括:

  • 主內(nèi)存 (Main Memory / RAM): 插在主板上的內(nèi)存條,是CPU主要的工作區(qū)域。
  • 顯卡顯存 (VRAM): 位于顯卡上的專用高速存儲器,用于存儲圖形數(shù)據(jù)和紋理。
  • 各種適配器上的 ROM 或 RAM: 例如,網(wǎng)卡、聲卡等設(shè)備上也可能有存儲固件(ROM)或少量用于緩沖數(shù)據(jù)的RAM。

這些物理存儲器是分散在計算機(jī)系統(tǒng)中的獨(dú)立硬件單元。它們各自有自己的控制器,以及訪問其內(nèi)部數(shù)據(jù)的機(jī)制。

2. 存儲地址空間 (Per-Device): 各自為政的地址范圍

每個物理存儲設(shè)備都有其內(nèi)部的存儲地址空間 (Storage Address Space)。這指的是該設(shè)備內(nèi)部用來標(biāo)識其存儲單元(通常是字節(jié))的地址范圍。

例如,一個 8GB 的內(nèi)存條,它內(nèi)部可能有從地址 0 到 8GB-1 的存儲單元。一塊顯卡的 4GB 顯存,它內(nèi)部也有從地址 0 到 4GB-1 的存儲單元。一個設(shè)備上的 ROM 可能有從地址 0 到 ROM 大小-1 的地址。

你可以把這想象成不同的建筑物,每棟建筑物里的房間都有從 1 開始編號。建筑物 A 的 1 號房間和建筑物 B 的 1 號房間是完全不同的兩個地方。每個物理設(shè)備就是一棟“建筑物”,它的內(nèi)部地址空間就是這棟建筑物里“房間”的編號范圍。

問題來了:CPU 如何統(tǒng)一管理和訪問這些分散在不同物理設(shè)備、擁有各自獨(dú)立地址空間的存儲單元呢?CPU 不能直接說“請給我建筑物 B 的 1 號房間的東西”。

3. 統(tǒng)一的視圖:內(nèi)存地址空間與線性地址

為了讓 CPU 和軟件能夠方便地訪問和管理這些分散的物理存儲資源,操作系統(tǒng)和硬件(特別是內(nèi)存管理單元 MMU)會將這些物理設(shè)備的地址映射 (Mapping) 到一個統(tǒng)一的、線性的地址空間中。這個統(tǒng)一的地址空間,就是我們通常在討論計算機(jī)系統(tǒng)時所說的內(nèi)存地址空間,或者更精確地說,是線性地址空間 (Linear Address Space),在現(xiàn)代操作系統(tǒng)中,它往往是虛擬地址空間 (Virtual Address Space) 的一部分。

這個過程可以理解為:系統(tǒng)為所有的物理存儲資源(包括 RAM、顯存、各種設(shè)備的寄存器和內(nèi)存等)編制了一個統(tǒng)一的“地圖”。地圖上的每一個地址都對應(yīng)著某個物理設(shè)備上的某個具體的存儲單元。

例如,在一個 32 位系統(tǒng)中,這個統(tǒng)一的線性地址空間通常是從地址 0x000000000xFFFFFFFF,總共 2^32 = 4GB 的地址范圍。系統(tǒng)會將 4GB 物理內(nèi)存的地址范圍映射到這個線性地址空間的一部分,將顯存映射到另一部分,將設(shè)備 ROM/RAM 映射到再一部分,等等。

這樣一來,CPU 只需要使用這個統(tǒng)一的線性地址(例如 0x80001234),系統(tǒng)硬件就會負(fù)責(zé)將這個線性地址翻譯成對應(yīng)的物理設(shè)備上的物理地址(例如“顯卡顯存上的地址 0x101234”),從而完成數(shù)據(jù)的訪問。

內(nèi)存地址 (Memory Address) 這個概念,在程序開發(fā)者的視角看來,通常指的就是在這個統(tǒng)一的線性/虛擬地址空間中的地址。當(dāng)我們在 C/C++ 中使用指針獲取變量地址時,獲取到的就是這個線性/虛擬地址空間中的地址。

將內(nèi)存抽象成字節(jié)數(shù)組:

從軟件(特別是操作系統(tǒng)和應(yīng)用程序)的角度看,這個統(tǒng)一的內(nèi)存地址空間可以被抽象成一個巨大的、一維的字節(jié)數(shù)組 (Byte Array)。這個數(shù)組的每一個“格子”就是一個字節(jié)(8 bits),并且都有一個唯一的、從 0 開始的編號,這個編號就是該字節(jié)的內(nèi)存地址。

  • 地址 0x00000000 對應(yīng)第一個字節(jié)。
  • 地址 0x00000001 對應(yīng)第二個字節(jié)。
  • ...
  • 地址 0xFFFFFFFF 對應(yīng)最后一個字節(jié)(在 32 位系統(tǒng)中)。

不同類型的數(shù)據(jù),如 char (1 字節(jié)), int (通常 4 字節(jié)), float (通常 4 字節(jié)), double (通常 8 字節(jié)),以及更復(fù)雜的結(jié)構(gòu)體和數(shù)組,它們在內(nèi)存中會占據(jù)連續(xù)的若干個字節(jié)空間。一個變量的地址通常指的就是它所占用的第一個字節(jié)的地址。

4. 代碼示例:窺探程序眼中的內(nèi)存地址

通過一個簡單的 C 語言程序,我們可以直觀地看到變量在程序所感知的這個“內(nèi)存地址空間”中是如何被分配地址的。

#include <stdio.h> // 包含標(biāo)準(zhǔn)輸入輸出庫,用于使用 printf 函數(shù)
#include <stddef.h> // 包含 stddef.h 以使用 size_t 類型

int main() {
    // 聲明不同類型的變量
    char my_char = 'A';        // 字符類型,通常占 1 字節(jié)
    int my_int = 12345;        // 整型,通常占 4 字節(jié)
    float my_float = 3.14f;    // 浮點(diǎn)型,通常占 4 字節(jié)
    double my_double = 2.71828; // 雙精度浮點(diǎn)型,通常占 8 字節(jié)

    // 聲明一個數(shù)組
    int my_array[5] = {10, 20, 30, 40, 50}; // 包含 5 個整型的數(shù)組

    // 聲明一個結(jié)構(gòu)體
    struct Point {
        int x;
        int y;
    };
    struct Point p = {100, 200}; // 結(jié)構(gòu)體變量

    // 聲明一個函數(shù) (實(shí)際上是獲取函數(shù)的入口地址)
    // 注意:函數(shù)地址通常在代碼段,與數(shù)據(jù)段/棧段的地址在不同的內(nèi)存區(qū)域
    void (*print_msg)(void) = main; // 獲取 main 函數(shù)的地址 (示例)
    // 實(shí)際調(diào)用函數(shù)指針的例子:
    // print_msg(); // 這會嘗試再次執(zhí)行 main 函數(shù),可能會導(dǎo)致棧溢出或其他問題,不建議在實(shí)際代碼中這樣做!
    // 這里的目的是演示如何獲取函數(shù)地址

    // 打印變量的值、地址和占用的字節(jié)數(shù)
    // %p 用于打印指針的值 (地址),需要轉(zhuǎn)換為 (void*) 類型以保證跨平臺兼容性
    // sizeof 運(yùn)算符用于獲取變量或類型占用的字節(jié)數(shù)
    printf("變量 my_char:\n");
    printf("  值: %c\n", my_char);
    printf("  地址: %p\n", (void*)&my_char);
    printf("  占用字節(jié)數(shù): %zu\n", sizeof(my_char)); // %zu 用于 size_t 類型

    printf("\n變量 my_int:\n");
    printf("  值: %d\n", my_int);
    printf("  地址: %p\n", (void*)&my_int);
    printf("  占用字節(jié)數(shù): %zu\n", sizeof(my_int));

    printf("\n變量 my_float:\n");
    printf("  值: %f\n", my_float);
    printf("  地址: %p\n", (void*)&my_float);
    printf("  占用字節(jié)數(shù): %zu\n", sizeof(my_float));

    printf("\n變量 my_double:\n");
    printf("  值: %lf\n", my_double); // %lf 用于 double 類型
    printf("  地址: %p\n", (void*)&my_double);
    printf("  占用字節(jié)數(shù): %zu\n", sizeof(my_double));

    printf("\n數(shù)組 my_array:\n");
    // 數(shù)組名本身通常代表數(shù)組第一個元素的地址
    printf("  數(shù)組首地址: %p\n", (void*)my_array);
    printf("  第一個元素 my_array[0] 的地址: %p\n", (void*)&my_array[0]);
    printf("  第二個元素 my_array[1] 的地址: %p\n", (void*)&my_array[1]);
    printf("  占用總字節(jié)數(shù): %zu\n", sizeof(my_array));
    printf("  每個元素占字節(jié)數(shù): %zu\n", sizeof(my_array[0]));
    // 注意觀察相鄰元素地址之間的差異,它等于元素的大小 (這里是 sizeof(int))

    printf("\n結(jié)構(gòu)體 p:\n");
    printf("  結(jié)構(gòu)體首地址: %p\n", (void*)&p);
    printf("  成員 p.x 的地址: %p\n", (void*)&p.x);
    printf("  成員 p.y 的地址: %p\n", (void*)&p.y);
    printf("  占用總字節(jié)數(shù): %zu\n", sizeof(p));
    // 注意成員地址與結(jié)構(gòu)體首地址的關(guān)系

    printf("\n函數(shù) main 的地址:\n");
    printf("  地址: %p\n", (void*)print_msg); // 打印函數(shù)指針的值

    return 0; // 程序正常結(jié)束
}

編譯和運(yùn)行:

  1. 將上述代碼保存為 address_example.c 文件。
  2. 打開終端或命令提示符。
  3. 使用 C 編譯器(如 GCC)編譯代碼:
gcc address_example.c -o address_example
  1. 運(yùn)行生成的可執(zhí)行文件:
./address_example

運(yùn)行結(jié)果示例:

請注意,輸出的內(nèi)存地址是示例值,具體數(shù)值在您的系統(tǒng)上運(yùn)行或每次運(yùn)行時都可能不同,因?yàn)椴僮飨到y(tǒng)會動態(tài)分配內(nèi)存,并且涉及到虛擬內(nèi)存地址。關(guān)鍵在于觀察地址的相對關(guān)系和不同類型占用的字節(jié)數(shù)。

變量 my_char:
  值: A
  地址: 0x7ffd7533f0b7
  占用字節(jié)數(shù): 1

變量 my_int:
  值: 12345
  地址: 0x7ffd7533f0b0
  占用字節(jié)數(shù): 4

變量 my_float:
  值: 3.140000
  地址: 0x7ffd7533f0ac
  占用字節(jié)數(shù): 4

變量 my_double:
  值: 2.718280
  地址: 0x7ffd7533f0a0
  占用字節(jié)數(shù): 8

數(shù)組 my_array:
  數(shù)組首地址: 0x7ffd7533f080
  第一個元素 my_array[0] 的地址: 0x7ffd7533f080
  第二個元素 my_array[1] 的地址: 0x7ffd7533f084
  占用總字節(jié)數(shù): 20
  每個元素占字節(jié)數(shù): 4

結(jié)構(gòu)體 p:
  結(jié)構(gòu)體首地址: 0x7ffd7533f078
  成員 p.x 的地址: 0x7ffd7533f078
  成員 p.y 的地址: 0x7ffd7533f07c
  占用總字節(jié)數(shù): 8

函數(shù) main 的地址:
  地址: 0x563e556c4179

結(jié)果分析:

  1. 每個變量都被分配了一個唯一的地址。這些地址是程序在運(yùn)行時看到的線性/虛擬地址。
  2. sizeof 運(yùn)算符顯示了不同數(shù)據(jù)類型占用的字節(jié)數(shù),這決定了它們在內(nèi)存中占據(jù)的空間大小。
  3. 對于數(shù)組 my_array,數(shù)組名 my_array 的地址與第一個元素 &my_array[0] 的地址相同。相鄰元素 &my_array[0] 和 &my_array[1] 的地址相差 4 個字節(jié) (0x7ffd7533f084 - 0x7ffd7533f080 = 0x4),正好是一個 int 類型的大小,這印證了數(shù)組元素是連續(xù)存儲的。
  4. 對于結(jié)構(gòu)體 p,結(jié)構(gòu)體的首地址就是其第一個成員 &p.x 的地址。第二個成員 &p.y 的地址緊隨其后(或者根據(jù)編譯器的對齊策略有微小的間隔),地址相差 4 個字節(jié) (0x7ffd7533f07c - 0x7ffd7533f078 = 0x4),正好是 p.x (int) 的大小,這說明結(jié)構(gòu)體成員也是按順序存儲的。結(jié)構(gòu)體的總大小是其成員大小的總和(加上可能的對齊填充)。
  5. 函數(shù) main 也有一個地址,這是函數(shù)代碼在內(nèi)存中的起始位置。函數(shù)的地址通常位于內(nèi)存的不同區(qū)域(代碼段)與變量(數(shù)據(jù)段/棧段)的地址區(qū)分開來。

這個例子清晰地展示了程序如何看待內(nèi)存——一個擁有連續(xù)地址的字節(jié)序列,各種數(shù)據(jù)類型根據(jù)其大小占據(jù)其中的一部分。操作系統(tǒng)和硬件在底層默默地將這些程序可見的地址翻譯成物理設(shè)備上的實(shí)際地址。

到此這篇關(guān)于計算機(jī)內(nèi)存探秘:物理存儲器、地址空間與內(nèi)存地址的文章就介紹到這了,更多相關(guān)計算機(jī)內(nèi)存:物理存儲器、地址空間與內(nèi)存地址內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • 到初創(chuàng)公司工作的五個理由

    到初創(chuàng)公司工作的五個理由

    這篇文章主要介紹了到初創(chuàng)公司工作的五個理由,在職業(yè)選擇上并不來一定要去大公司,去初創(chuàng)公司工作一次會讓你有更多的收獲,需要的朋友可以參考下
    2014-09-09
  • Markdown語法手冊—完整筆記整理

    Markdown語法手冊—完整筆記整理

    Markdown是一種輕量級標(biāo)記語言,創(chuàng)始人為約翰·格魯伯(John?Gruber),?它允許人們使用易讀易寫的純文本格式編寫文檔,然后轉(zhuǎn)換成有效的?XHTML(或者HTML)文檔,由于Markdown的輕量化、易讀易寫特性,并且對于圖片,圖表、數(shù)學(xué)式都有支持,許多網(wǎng)站都廣泛使用Markdown
    2024-08-08
  • Uint?和?int?的區(qū)別解析

    Uint?和?int?的區(qū)別解析

    Int與Uint的區(qū)別在于帶符號與不帶符號,在計算機(jī)中根據(jù)補(bǔ)碼進(jìn)行互相轉(zhuǎn)換,很多語言是有方法支持的,但是也有一些并沒有轉(zhuǎn)換方法,比如SQLserver(SQLserver不支持Uint類型),下面詳細(xì)介紹Uint?和?int?的區(qū)別,感興趣的朋友一起看看吧
    2023-08-08
  • 有意思的數(shù)據(jù)結(jié)構(gòu)默克樹 Merkle tree應(yīng)用介紹

    有意思的數(shù)據(jù)結(jié)構(gòu)默克樹 Merkle tree應(yīng)用介紹

    這篇文章主要為大家介紹了有意思的數(shù)據(jù)結(jié)構(gòu)默克樹 Merkle tree應(yīng)用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • centos部署open-webui的完整流程記錄

    centos部署open-webui的完整流程記錄

    這篇文章主要介紹了centos部署open-webui的完整流程,OpenWebUI是一個開源的Web用戶界面工具,用于與本地或私有化部署的大語言模型交互,文中將步驟介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • 鴻蒙系統(tǒng)中的Webview技術(shù)使用方法詳解

    鴻蒙系統(tǒng)中的Webview技術(shù)使用方法詳解

    webView類是View類的一個擴(kuò)展,用來顯示網(wǎng)頁,它不包含任何的網(wǎng)頁瀏覽器的特征,像沒有導(dǎo)航控制和地址欄,使用起來也很方便,這篇文章主要給大家介紹了關(guān)于鴻蒙系統(tǒng)中Webview技術(shù)使用的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • idea啟動后CPU飆升的問題解決

    idea啟動后CPU飆升的問題解決

    IDEA運(yùn)行大型項目,項目啟動卡頓,CPU使用率占用過高,下面這篇文章主要給大家介紹了關(guān)于idea啟動后CPU飆升的問題解決,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • github版本庫使用詳細(xì)圖文教程(命令行及圖形界面版)

    github版本庫使用詳細(xì)圖文教程(命令行及圖形界面版)

    今天我們就來學(xué)習(xí)github的使用,我們將用它來管理我們的代碼,你會發(fā)現(xiàn)它的好處的,當(dāng)然是要在本系列教程全部完成之后,所以請緊跟站長的步伐,今天是第一天,我們來學(xué)習(xí)如何在git上建立自己的版本倉庫,并將代碼上傳到倉庫中
    2015-08-08
  • 詳情解析TCP與UDP傳輸協(xié)議

    詳情解析TCP與UDP傳輸協(xié)議

    本文通過講解TCP與UDP傳輸協(xié)議傳輸數(shù)據(jù)是的過程及詳細(xì)介紹什么是 socket及現(xiàn)在我么們和大家一起來學(xué)習(xí)吧
    2021-08-08
  • 最新IDEA永久激活教程(支持最新2019.2版本)

    最新IDEA永久激活教程(支持最新2019.2版本)

    這篇文章主要介紹了最新IDEA永久激活教程,此教程已支持最新2019.2版本,適用Windows、Mac、Ubuntu等所有平臺,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05

最新評論