1

我无法理解某些指针的工作原理。我一直认为,当你创建一个指针变量 (p) 时,你不能尊重和分配 (*p = value),除非你为它分配了空间 (p = malloc(x)),或者将它设置为另一个变量的地址 (p = &a)

但是在这段代码中,第一个分配始终如一,而最后一个导致段错误:

typedef struct
{
    int value;
} test_struct;

int main(void)
{
    //This works
    int* colin;
    *colin = 5;

    //This never works
    test_struct* carter;
    carter->value = 5;
}

当 colin 没有指向任何空闲内存时,为什么第一个工作?为什么第二个永远不起作用?

我是用 C 写的,但是有 C++ 知识的人也应该能够回答这个问题。

编辑:好的,我知道第一个也不应该工作,但为什么会这样。这就是我所追求的。

4

4 回答 4

7
// This works
int* colin;
*colin = 5;

欢迎来到未定义的行为:它不会崩溃的事实并不意味着它可以工作。访问未初始化的指针总是错误的,但有时它不会崩溃。

除非您为其分配空间或将其设置为另一个变量的地址,否则无法服从和分配

这是对的。通常,您需要将指针指向已分配给程序的某个位置。有多种方法可以做到这一点,但它们都归结为您描述的两种情况之一 - 指针指向动态分配的内存(即malloc)或静态分配的内存(即变量)。

于 2013-06-25T10:17:39.727 回答
2

我一直认为,当你创建一个指针变量 (p) 时,你不能尊重和分配 (*p = value),除非你为它分配了空间 (p = malloc(x)),或者将它设置为另一个变量的地址 (*p = &a)

出于实际目的,您认为正确。最好继续这样想。

如果您执行示例中的操作,则程序的行为是未定义的。这意味着任何事情都可能发生,包括一种误导性的“工作”感觉。但这不过是灾难的秘诀。

于 2013-06-25T10:18:25.963 回答
1

我一直认为,当你创建一个指针变量 (p) 时,你不能尊重和分配 (*p = value),除非你为它分配了空间 (p = malloc(x)),或者将它设置为另一个变量的地址 (*p = &a)

C 中有些东西是不允许的,所以 C 编译器会发出错误并拒绝编译程序,还有一些 C 标准没有定义任何行为的东西,所以对实现的内容没有限制做...这样做的原因是为实现提供了很大的自由度来决定它们的实现方式,并允许它们生成非常快速的代码。这与更现代的语言不同,后者更重视保护程序员免受自身错误的影响。因此,程序员编写有效代码的负担更大。

您的代码是行为未定义的示例。当您取消引用并分配它时,编译器不会生成检查以查看值p是否有效......它可能包含垃圾并且存储可能是内存中的任意位置,或者它可能指向不可访问的内存并且存储将崩溃(由于行为未定义,还有其他可能性,但这些是常见的现实世界实现中会发生的可能性)。您的代码在一个商店崩溃但在另一个商店没有崩溃纯属偶然,是实现细节的产物......不同的编译器,不同版本的编译器,对源代码的轻微更改......其中任何一个事物和其他人可以通过改变碰巧存在的价值来改变结果p...在堆栈上留下一些任意值,因为p是堆栈变量(C 语言标准没有强制甚至提到堆栈,但常见的现实世界实现auto在堆栈上分配变量。)

最重要的是,如您所知,您的程序是错误的,即使它是“允许的”。正如 R. Martinho Fernandes 在评论中所说,你很不幸,第一家商店“工作”......在商业产品中,拥有类似“工作”的东西将是非常不幸的,因为它随时可能失败,包括最坏的情况。C 语言在这里对你没有帮助……你需要非常自律。

于 2013-06-25T10:34:04.737 回答
0

不要看起来像“我也是!” 答案,但其他答案不能回答您的核心问题:

好的,我知道第一个也不应该工作,但为什么会这样。这就是我所追求的。

在这种情况下,您正在调用未定义的行为。C 和 C++ 标准都清楚地表明,当变量未初始化时,其内容是 undefined。当它说未定义时,它意味着未知。这些指针实际上可以包含任何内容。因为它们未初始化,所以它们包含编译器为这两个变量选择的位置上的任何内存。

在这种情况下,您的第一个变量恰好包含一个指向程序内存空间内的指针。第二个恰好包含一个指向程序内存空间之外的指针。它可以是从空指针到指向您的main函数的指针的任何内容。不管是什么,都无关紧要:你不需要知道或关心,因为它是垃圾。无论如何,您都应该重写它。

调用未定义的行为会使恶魔从你的鼻子里飞出来,这是 C 程序员中的一个常见说法。这是因为 C 标准非常明确地指出,当行为未定义时,编译器可以自由地做想做的任何事情。这包括发射核导弹,将你的银行账户重置为零,或者,是的,让有翼生物从你的鼻腔中飞出。

于 2013-06-25T10:32:17.677 回答