我能访问地址0吗? 常数0用作C和C++中的空指针。但正如在问题中一样,分配固定地址似乎有一些可能的用途。在任何系统中,对于任何低级任务,访问地址0是否有任何可能的需求
如果有,如何解决0是空指针和all的问题我能访问地址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也称为。它由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)