简体   繁体   English

指向结构的指针

[英]pointer to a structure

this will give a proper output even though i have not allocated memory and have declared a pointer to structure two inside main 即使我尚未分配内存并声明了一个指向main内部结构2的指针,这也将提供适当的输出

    struct one
    {
    char x;
    int y;
    };

    struct two
    {
    char a;
    struct one * ONE;
    };

    main()
    {
    struct two *TWO;
    scanf("%d",&TWO->ONE->y);
    printf("%d\n",TWO->ONE->y);
    }

but when i declare a pointer to two after the structure outside main i will get segmentation fault but why is it i don't get segmentation fault in previous case 但是当我在main外部的结构之后声明一个指向2的指针时,我将得到分段错误,但是为什么在以前的情况下我没有得到分段错误

    struct one
    {
    char x;
    int y;
    };

    struct two
    {
    char a;
    struct one * ONE;
    }*TWO;


    main()
    {
    scanf("%d",&TWO->ONE->y);
    printf("%d\n",TWO->ONE->y);
    }

In both the cases TWO is a pointer to a object of type struct two . 在这两种情况下, TWO都是指向 struct two类型的对象的指针

In case 1 the pointer is wild and can be pointing anywhere. 在情况1中,指针是野生的,可以指向任何地方。

In case 2 the pointer is NULL as it is global. 在情况2中,指针是NULL因为它是全局的。

But in both the cases it a pointer not pointing to a valid struct two object. 但是在两种情况下,它都没有指向有效的 struct two对象的指针。 Your code in scanf is treating this pointer as though it was referring to a valid object. 您在scanf代码会将这个指针当作指向有效对象一样对待。 This leads to undefined behavior. 这导致未定义的行为。

Because what you are doing is undefined behaviour. 因为您正在做的事情是不确定的行为。 Sometimes it seems to work. 有时似乎可行。 That doesn't mean you should do it :-) 这并不意味着您应该这样做:-)

The most likely explanation is to do with how the variables are initialised. 最可能的解释与变量的初始化方式有关。 Automatic variables (on the stack) will get whatever garbage happens to be on the stack when the stack pointer was decremented. 当堆栈指针递减时,自动变量(在堆栈上)将获得碰巧在堆栈上的所有垃圾。

Variables outside functions (like in the second case) are always initialised to zero (null pointer for pointer types). 函数外部的变量(如第二种情况)始终初始化为零(指针类型为空指针)。

That's the basic difference between your two situations but, as I said, the first one is working purely by accident. 这是您的两种情况之间的基本区别,但是,正如我所说,第一种情况纯粹是出于偶然。

When declaring a global pointer, it will be initialized to zero, and so the generated addresses will be small numbers that may or may not be readable on your system. 声明全局指针时,它将被初始化为零,因此生成的地址将是较小的数字,在您的系统上可能无法读取。

When declaring an automatic pointer, its initial value is likely to be much more interesting. 声明自动指针时,其初始值可能会更有趣。 It will be, in this case, whatever the run-time library left at that point on the stack prior to calling main(), or perhaps a left-over value from the compiler-generated stack-frame setup code. 在这种情况下,它将是调用main()之前在堆栈上的那个剩余运行时库,或者是编译器生成的堆栈框架设置代码中的剩余值。 It is somewhat likely to be a saved stack pointer or frame pointer, which is a valid pointer if used with small offsets. 它可能是保存的堆栈指针或帧指针,如果与小偏移量一起使用,则是有效的指针。

So anyway, the uninitialized pointer does have something in it, and one value leads to a fault while the other, for now, on your system, does not. 因此,无论如何,未初始化的指针中确实包含某些内容,一个值导致错误,而到目前为止,系统上的另一个值却没有。

And that's because the segmentation fault is a mechanism of the OS and not the C language. 那是因为分段错误是OS的机制,而不是C语言的机制。

A fault is a block-based mechanism that allocates to itself and other programs some number of pages -- which are each several K -- and it protects itself and other program's pages while allowing your program free reign. 故障是一种基于块的机制,可以为自身和其他程序分配一定数量的页面(每个页面数K),并在允许程序自由运行的同时保护自身和其他程序的页面。 You must stray outside of the block context or try to write a read-only page (even if yours) to generate a fault. 您必须在块上下文之外迷路,或者尝试编写一个只读页面(即使您的页面也是这样)以生成错误。 Simply breaking a language rule is not necessarily enough. 仅仅打破语言规则并不一定足够。 The OS is happy to let your program misbehave and act oddly due to its wild references, just as long as it only reads and writes (or clobbers) itself. 操作系统很乐意让您的程序由于其狂野的引用而行为异常,并采取奇怪的行动,只要它本身仅读取和写入(或复制)它们即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM