相关疑难解决方法(0)

为什么地址零用于空指针?

在C(或C++)中,指针是特殊的,如果它们的值为零:我建议在释放内存后将指针设置为零,因为这意味着再次释放指针并不危险; 当我调用malloc时,如果它无法获取内存,则返回一个值为零的指针; 我一直用if (p != 0)它来确保传递的指针是有效的,等等.

但是,由于内存寻址从0开始,因此有效地址不是0吗?如果是这样的话,0如何用于处理空指针?为什么不是负数而是null?


编辑:

一堆好的答案.我将总结在所表达的答案中所说的内容,因为我自己的思想解释了它,并希望如果我误解,社区将纠正我.

  • 就像编程中的其他一切一样,它是一种抽象.只是一个常量,与地址0并不真正相关.C++ 0x通过添加关键字来强调这一点nullptr.

  • 它甚至不是地址抽象,它是C标准指定的常量,只要它确保它永远不等于"真实"地址,编译器就可以将它转换为其他数字,如果0不是,则等于其他空指针用于平台的最佳价值.

  • 如果它不是抽象,早期就是这种情况,系统使用地址0,程序员不受限制.

  • 我承认,我的负面数字建议是一个狂热的头脑风暴.对地址使用有符号整数有点浪费,如果它意味着除了空指针(-1或其他)之外,值空间在产生有效地址的正整数和刚刚浪费的负数之间均匀分配.

  • 如果任何数字总是可以由数据类型表示,那么它就是0.(也可能是1.我想的是一位整数,如果是无符号则为0或1,或者只有符号的有符号位,或两位整数,将是[-2,1].但是你可以只得0为空,1是内存中唯一可访问的字节.)

还有一些东西在我的脑海里没有得到解决.Stack Overflow问题指向特定固定地址的指针告诉我,即使0表示空指针是抽象,其他指针值也不一定.这导致我发布另一个Stack Overflow问题,我是否可以访问地址零?.

c c++ memory pointers

119
推荐指数
6
解决办法
3万
查看次数

为什么这个指针为空

在 Visual Studio 中,成员变量的指针似乎在幕后是 32 位有符号整数(即使在 64 位模式下),并且在该上下文中空指针为 -1。所以如果我有一个类:

#include <iostream>
#include <cstdint>

struct Foo
{
    char arr1[INT_MAX];
    char arr2[INT_MAX];
    char ch1;
    char ch2;
};


int main()
{
    auto p = &Foo::ch2;
    std::cout << (p?"Not null":"null") << '\n';
}
Run Code Online (Sandbox Code Playgroud)

它编译并打印“null”。那么,是我造成了某种未定义的行为,还是编译器应该拒绝此代码而这是编译器中的错误?

编辑:

看来我可以保留“2 个INT_MAX数组加 2 个字符”模式,只有在这种情况下,编译器才允许我添加任意数量的成员,并且第二个字符始终被视为空值。见演示。如果我稍微改变了模式(比如在某个时候用 1 或 3 个字符而不是 2 个字符),它会抱怨这个类太大了。

c++ visual-studio language-lawyer

32
推荐指数
2
解决办法
1053
查看次数

指向特定固定地址的指针

如何为指针分配特定的内存地址?

微控制器中的特殊功能寄存器如AVR m128具有固定地址,AVR GCC在io.h头文件中定义了SFR,但我想自己处理它.

c pointers

13
推荐指数
1
解决办法
2万
查看次数

具有未定义结果的C代码,编译器生成无效代码(使用-O3)

我知道当你在C程序中做某些事情时,结果是不确定的.但是,编译器不应该生成无效(机器)代码,对吧?如果代码做错了,或者代码生成了段错误或其他什么,那将是合理的......

这应该是根据编译器规范发生的,还是编译器中的错误?

这是我正在使用的(简单)程序:

int main() {
    char *ptr = 0;
    *(ptr) = 0;
}
Run Code Online (Sandbox Code Playgroud)

我正在编译-O3.那不应该生成无效的硬件指令,对吧?有了-O0,我在运行代码时遇到了段错误.这看起来更加明智.

编辑:它正在生成一条ud2指令......

c gcc undefined-behavior

7
推荐指数
1
解决办法
1555
查看次数

NULL保证为0吗?

我想知道是否NULL保证使用0C++,所以我搜索并发现了这些:


这个答案表明:

这是Bjarne Stroustrup的措辞,

在C++中,NULL的定义是0,因此只有美学差异.我更喜欢避免宏,所以我使用0. NULL的另一个问题是人们有时会错误地认为它与0不同和/或不是整数.

这似乎证实NULL总是0.


但根据cppreference.com:

#define NULL /*implementation-defined*/
Run Code Online (Sandbox Code Playgroud)

宏NULL是一个实现定义的空指针常量,可能是:

- >整数类型的整数常量表达式rvalue,其计算结果为零(直到C++ 11)

- >值为零的整数文字,或类型为std :: nullptr_t的prvalue(自C++ 11起)

这清楚地说NULL是依赖于实现.


这个答案说:

0(也称为C的NULL桥接到C++中)可能导致重载函数解析的模糊性,除其他外:

f(int); 
f(foo *);
Run Code Online (Sandbox Code Playgroud)

这再次暗示这NULL是整数0,可能会导致歧义


我遇到了其他问题和答案,但它们主要是关于C语言,而不是C++.这里的一个评论说:

并且NULL保证为0

但同样,这是关于C.


总而言之,NULL总是0在C++中?C怎么样?是(对于每个标准实现)是否相同:

#define NULL 0
Run Code Online (Sandbox Code Playgroud)

注意:这个问题与空指针无关,问题是NULL在C++中是否保证是0整数.它是依赖于实现的吗?

c++ null

7
推荐指数
1
解决办法
491
查看次数

指针地址跨越各种平台

在C中编码时的常见情况是编写返回指针的函数.如果在运行期间写入函数内发生某些错误,NULL可能会返回以指示错误.NULL只是特殊的内存地址0x0,除了表示特殊条件的出现之外,它从不用于任何东西.

我的问题是,是否有任何其他特殊的内存地址永远不会用于用户态应用程序数据?

我想知道这个的原因是因为它可以有效地用于错误处理.考虑一下:

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

#define ERROR_NULL 0x0
#define ERROR_ZERO 0x1

int *example(int *a) {
    if (*a < 0)
        return ERROR_NULL;
    if (*a == 0)
        return (void *) ERROR_ZERO;
    return a;
}

int main(int argc, char **argv) {
    if (argc != 2) return -1;
    int *result;
    int a = atoi(argv[1]);
    switch ((int) (result = example(&a))) {
        case ERROR_NULL:
            printf("Below zero!\n");
            break;

        case ERROR_ZERO:
            printf("Is zero!\n");
            break;

        default:
            printf("Is %d!\n", *result);
            break;
    }
    return 0; …
Run Code Online (Sandbox Code Playgroud)

c error-handling pointers void-pointers memory-address

0
推荐指数
1
解决办法
260
查看次数