我能访问地址0吗? 常数0用作C和C++中的空指针。但正如在问题中一样,分配固定地址似乎有一些可能的用途。在任何系统中,对于任何低级任务,访问地址0是否有任何可能的需求

我能访问地址0吗? 常数0用作C和C++中的空指针。但正如在问题中一样,分配固定地址似乎有一些可能的用途。在任何系统中,对于任何低级任务,访问地址0是否有任何可能的需求,c++,c,memory,pointers,C++,C,Memory,Pointers,如果有,如何解决0是空指针和all的问题 如果没有,是什么确保没有这种需要?内存地址0也称为。它由BIOS填充,并包含有关系统上运行的硬件的信息。所有现代内核都保护这一内存区域。您应该永远不需要访问这个内存,但是如果您想访问它,您需要从内核区内部访问它,内核模块就可以做到这一点 在x86上,地址0(或者更确切地说,0000:0000)及其附近的实模式是中断向量的位置。在糟糕的过去,您通常会将值写入中断向量以安装中断处理程序(或者如果您更严格,则使用MS-DOS服务0x25)。MS-DOS的C编译

如果有,如何解决0是空指针和all的问题


如果没有,是什么确保没有这种需要?

内存地址0也称为。它由BIOS填充,并包含有关系统上运行的硬件的信息。所有现代内核都保护这一内存区域。您应该永远不需要访问这个内存,但是如果您想访问它,您需要从内核区内部访问它,内核模块就可以做到这一点

在x86上,地址0(或者更确切地说,0000:0000)及其附近的实模式是中断向量的位置。在糟糕的过去,您通常会将值写入中断向量以安装中断处理程序(或者如果您更严格,则使用MS-DOS服务0x25)。MS-DOS的C编译器定义了一种远指针类型,当赋值为NULL或0时,将在其段部分接收位模式0000,在其偏移部分接收位模式0000


当然,一个不正常的程序意外地写入了一个值为0000:0000的远指针,这会导致机器发生非常糟糕的事情,通常会将其锁定并强制重新启动。

在链接中的问题中,人们正在讨论在微控制器中设置固定地址的问题。当你编程一个微控制器时,所有的东西都处于一个低得多的水平


你甚至没有台式机/服务器PC的操作系统,也没有虚拟内存之类的东西。因此,访问特定地址的内存是正常的,甚至是必要的。在现代的台式机/服务器PC上,它是无用的,甚至是危险的。

编译器会为您解决这个问题():

如果一台机器对空指针使用非零位模式,则编译器有责任在程序员请求时通过编写“0”或“null”空指针来生成它。因此,在内部空指针非零的机器上,将空指针定义为0与在任何其他机器上一样有效,因为编译器必须(并且可以)仍然生成机器的正确空指针,以响应指针上下文中看到的未加修饰的0


可以通过从非指针上下文引用零来获得零地址。< / P> < P>切线注释:您可能感兴趣地知道,用微软的C++编译器,一个空指针指向成员将被表示为32位机器上的位模式0xFFFFFFF。即:

struct foo
{
      int field;
};

int foo::*pmember = 0;     // 'null' member pointer
pmember将具有位模式“所有的”。这是因为您需要此值来将其与

int foo::*pmember = &foo::field;
其中,位模式实际上会被“全零”替换——因为我们希望偏移量0进入结构foo


<> P>其他C++编译器可以为成员的空指针选择不同的位模式,但关键的观察点是它不是你所期望的全零位模式。在运行时检查每个指针操作是否有空指针会有点昂贵。在计算机上,程序将崩溃,因为操作系统禁止它。在没有内存保护的嵌入式系统上,程序确实会写入地址0,这通常会使整个系统崩溃


地址0在嵌入式系统上可能很有用(这是不在计算机中的CPU的通用术语;它们运行从立体声到数码相机的一切)。通常,系统的设计不需要写入地址0。据我所知,这是一个特殊的地址。即使程序员需要对其进行写入(例如,设置一个中断表),他们也只需要在初始启动序列期间对其进行写入(通常使用一小段汇编语言来设置C环境)。

这一切都取决于机器是否有虚拟内存。使用它的系统通常会在那里放置一个不可写的页面,这可能是您习惯的行为。然而,在没有它的系统中(现在通常是微控制器,但它们过去更为常见),在这方面通常有非常有趣的东西,比如中断表。我记得早在8位系统的时代,我就开始用这些东西进行黑客攻击;有趣,而且当您必须硬重置系统并重新开始时,不会有太大的痛苦。:-)

你从一个错误的前提开始。将值为0的整数常量赋给指针时,该值将变为空指针常量。但是,这并不意味着空指针必然指向地址0。恰恰相反,C和C++标准都很清楚,空指针可以指除0以外的某个地址。 归根结底是这样的:您必须留出一个空指针将引用的地址——但它基本上可以是您选择的任何地址。当您将零转换为指针时,它必须引用所选的地址——但这才是真正需要的。例如,如果您决定将一个整数转换为一个点意味着将0x8000添加到该整数,那么指向的空指针实际上将引用地址0x8000,而不是地址0

还值得注意的是,取消对空指针的引用会导致未定义的行为。这意味着你不能在可移植代码中实现它,但这并不意味着你根本不能实现它。当您为小型微控制器等编写代码时,通常会包含一些根本不可移植的代码。从一个地址读取可能会得到某个传感器的值,而向同一地址写入可能会激活步进电机(例如)。下一个设备(即使使用完全相同的处理器)可能是c
uintptr_t address = 0;
void *p = (void *) address;
void *p = 0;
      char *null = 0;
; Clears 8-bit AR and BR and stores it as a 16-bit pointer on the stack.
; The stack pointer, ironically, is stored at address 0.
1b:   4f              clra
1c:   5f              clrb
1d:   de 00           ldx     *0 <main>
1f:   ed 05           std     5,x
; addr is a pointer stored at 7,x (offset of 7 from the address in XR) and 
; the "NULL" pointer is at 5,y (offset of 5 from the address in YR).  It doesn't
; treat the so-called NULL pointer as a special pointer, which is not standards
; compliant as far as I know.
37:   de 00           ldx     *0 <main>
39:   ec 07           ldd     7,x
3b:   18 de 00        ldy     *0 <main>
3e:   cd a3 05        cpd     5,y
41:   26 10           bne     53 <.LM7>
int* i = new int(); // suppose this returns a pointer to address zero
*i = 42; // now we're accessing address zero, writing the value 42 to it
int i = 0;
int* zeroaddr = (int*)i;
int main(int argc, char *argv[])
{
    void *p = NULL;
    return 0;
}
int main(int argc, char *argv[])
{
    int *p = 0;
    *p = 42;
    int x = *p; /* let's assume C99 */
}
#include <stdio.h>
int main(int argc, char *argv[])
{
        int *p = NULL;
        printf("NULL is address %p\n", p);
        printf("Contents of address NULL is %d\n", *p);
        return 0;
}
NULL is address 0x0
Segmentation fault (core dumped)