0

I have created node structure and created pointer of the same inside main but didn't allocated memory for node structure : struct node * first or struct node * second (which was supposed to be allocated dynamically- malloc/calloc). Instead, I am able to access data(or memory for structure)

#include<stdio.h>
struct node{
    int data;
    struct node *next;
};
void Traverse(struct node * head){
    while (head!=NULL)
    {
        printf("Data:%d\n", head->data);
        head=head->next;
    }
}
int main()
{
    struct node * first;
    struct node * second;
    first->data=33;
    first->next=second;

    second->data=45;
    second->next=NULL;

    Traverse(first);
    return 0;

}

Currently I am running this code in VS Code so is this the VS Code which is doing it automatically or something else is happening internally?

rioV8
  • 24,506
  • 3
  • 32
  • 49
Victor
  • 83
  • 2
  • 8
  • I once worked with a C++ compiler that initialized pointers in debug mode with the value `DEADBEEF`, an always illegal address, that will get you a segmentation fault. And also pointers used in a `free()` call. – rioV8 Mar 29 '22 at 02:39
  • @rioV8 actually [0xCCCCCCCC is better](https://stackoverflow.com/q/370195/995714) because it works for all types instead of only pointers. You'll quickly realize the abnormal bit pattern or value in a non-pointer variable – phuclv Mar 29 '22 at 03:13
  • @phuclv For Intel x86 based systems it is but this was an SGI MIPS system – rioV8 Mar 29 '22 at 09:33
  • @rioV8 it's better for all platforms when you have a defined repeated platform, because it'll produce a uniform unepxected result when you read it as char, int, long... whatever. You know you're reading out of border when the string ends with a series of weird Korean characters, or when the array contains all similar bytes. When 0xDEADBEEF it's only good for pointers but not for data – phuclv Mar 29 '22 at 10:43
  • @phuclv Unless you are a Korean programmer ;-) – rioV8 Mar 29 '22 at 12:58

2 Answers2

4

Welcome to the land of undefined behavior.

C doesn't perform any bound checking on arrays or checks to see if a pointer is valid before using it. That's part of what makes C fast. The language trusts the user to follow the rules without explicitly enforcing them. So when you break the rules, you might "get caught", or you might not.

In this case you got "lucky" that your code happened to work, but there's no guarantee that will be the case. You could make a seemingly unrelated change such as adding a call to printf for debugging or adding an unused local variable and all of a sudden your code crashes.

dbush
  • 205,898
  • 23
  • 218
  • 273
4

If your definition of "work" is "apparently seems okay despite the fact it shouldn't be" then, yes, it works. However, I would contend that the correct definition of "works" should include the term "reliably" somewhere in it :-)

What you are doing there is undefined behaviour. This code specifically (inside a function, so using automatic variables):

struct node * first;
first->data = 33;

will assign an arbitrary value to first which may or may not fail when assigning data to the memory it points to. But, whether it fails or not, it's still the wrong thing to do. Possible outcomes include (non-exhaustive):

  • writing to memory that's protected, so probably a crash.
  • writing to memory unused by anything else so probably no effect.
  • writing to memory used by anything else so things will change in weird, unexpected ways.

Undefined behaviour is, well, ... undefined. That includes the subset of behaviour where it seems to work okay. But, if you rely on that, you will eventually suffer the consequences.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953