为什么通配指针保存零地址而不是垃圾地址?

时间:2020-05-13 05:02:35

标签: c++ c pointers

我一直在尝试查找特定数据类型(例如“ int”)的大小,而不使用sizeof()并发现了这个问题:

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
                //configure to require client certificate
                webBuilder.ConfigureKestrel(o =>
                {
                    o.ConfigureHttpsDefaults(o =>
                        o.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
                });
            });

这将返回int的正确大小。怎么样? 不是狂野的指针应该包含垃圾地址而不是零。并且如果它包含零,那么它与NULL指针有什么不同,因为NULL为(void *)0?

3 个答案:

答案 0 :(得分:3)

由于ptr尚未初始化,因此其值是不确定的,访问其值会产生不确定的行为。具有讽刺意味的是,“未定义”的含义由C和C ++标准定义,意为诸如“该标准不限制会发生的事情”之类的东西。

初学者经常错误地认为这意味着它必须包含“垃圾值”或“野生指针”或“在此处添加一些生动的描述”,但事实并非如此。

“值是不确定的”或“未定义访问值的行为”的含义是,访问该值的代码允许任何行为。

访问该值对于打印它,增加它或(如果是指针的话)取消引用它是必需的(访问由指针的值标识的地址的内容)。

访问该值的代码的行为是不确定的。给出的打印值为零,42或“垃圾值”都是正确的结果。但是,同样地,结果可能意味着没有输出或采取不良措施,例如重新格式化硬盘。如果重复执行代码,则行为甚至可能随时间改变。或者它可能是100%可重复的(对于特定的编译器,特定的操作系统,特定的硬件等)。

实际上,具有未定义行为的代码在程序测试期间不会给出任何故障迹象,但是后来在客户的计算机上安装并执行该程序时,会引起一些讨厌的,可见的但意想不到的效果。这往往会导致客户脾气暴躁,错误报告可能会导致开发人员无法复制,并且会给开发人员带来压力,试图修复该漏洞。

试图解释为什么未定义的行为会导致某些特定结果(例如打印零值)是没有意义的。

答案 1 :(得分:0)

  • “为什么野生指针持有零地址而不是垃圾地址?” 他们没有。 垃圾意味着任何东西;甚至为零。某些编译器可能具有特殊功能来解决默认初始化(但据我所知,这不是标准要求的)–检查生成的代码。

  • “这将返回正确的int大小。” 不,不是。它只是打印一些垃圾,这些垃圾可能正是您要寻找的

您可能正在寻找类似于以下代码的内容;之所以有效,是因为它基于两个连续地址之间的差异。请注意,sizeof是一个编译时运算符,下面的代码在运行时计算大小(但是,编译器可能会用一个常量替换它)。

    int* p = 0;
    int sizeof_int = (char*)(p + 1) - (char*)p; // works with uninitialized p, too

答案 2 :(得分:-2)

第一次打印将为垃圾或零,这取决于您的编译器和内存位置中的先前值。 如果它为零,则第二个打印将具有int的大小,因为增加指针会随着指针的大小而增加。

例如:

char *x = 0;
x++; //x=1

int *y = 0;
y++; //y=4

在您的情况下,如果您在第一次打印时得到0,则与将其初始化为NULL相同,但是您不能将其始终计数为零

>