3

Sorry for such a noob question When I am declaring a struct and giving it size 80 it's giving segmentation fault.T tried resources but could'nt understand the mistake and the error is also not giving me any more details.... here is my code -

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

struct stack
{
    int size;
    int top;
    int *arr;
};

int isEmpty(struct stack *ptr)
{
    if (ptr->top == -1)
    {
        return 1;
    }
    else
    {

        return 0;
    }
}

int isfull(struct stack *ptr)
{
    if (ptr->top == (ptr->size - 1))
    {
        return 1;
    }
    return 0;
}

int main()
{
    printf("Test\n");
    struct stack *s;
    s->size = 80; //segmentation error occurs here
    printf("Test\n");
    s->top = -1;
    s->arr = (int *)malloc(s->size * sizeof(int));
    // printf("Test\n");
    printf("%d",isEmpty(s));
    if (isEmpty(s))
    {
        printf("stack is empty");
    }
    else
    {
        printf("Not empty");
    }

    return 0;
}

when I am declaring size 80 of struct s it's giving segmentation error and I don't know why

Thanks in advance

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • 2
    Your pointer is uninitialized, therefore dereferencing it is not good. Why `*s`? Try `s`. (And `isEmpty(&s)`.) – Neil Sep 11 '22 at 14:28

3 Answers3

4

You declare a pointer to a struct, not a struct.

In order to fix the segmentation fault, allocate memory to the struct pointed to by the pointer:

struct stack *s;
s = malloc(sizeof(struct stack)); // Check for errors before using it.
s->size = 80; // No more segfault

Don't forget to free() later. Also check for malloc errors before using the pointer.

0xRyN
  • 852
  • 2
  • 13
2
struct stack *s;
s->size = 80;

s is a pointer to a struct, it is not a struct. Furthermore s is a uninitialized pointer. This means its value is not exactly known, established or defined. Trying to access the pointer invokes undefined behavior.

To fix your problem you must allocate some memory that the pointer will point to:

struct stack *s = malloc(sizeof(*s));

if (s == NULL) {
    // malloc() failed
}   

Also remember to free() the pointer once you are done with it:

struct stack *s = malloc(sizeof(*s));

if (s == NULL) {
    // malloc() failed
}   

...

free(s);

Notes:

  • It is not necessary to cast the return value of malloc().
programmer
  • 669
  • 3
  • 11
1

Sorry for such a noob question When I am declaring a struct and giving it size 80 it's giving segmentation fault.

But you're not declaring a struct. This ...

    struct stack *s;

... declares a pointer (that can point to a struct stack). It does not create a struct for it to point to, nor even assign an initial (pointer) value to s.

When the program then attempts ...

    s->size = 80;

... it is attempting to access an object (*s) that does not exist. The resulting behavior is undefined, and in practice, a segfault is a common result of such code.

Other answers suggest allocating memory for s to point to, and that would work, but better in this case would be to declare an actual struct instead of a pointer to one:

    struct stack s;  // not a pointer

Perhaps you chose a pointer because you saw or knew that you would need to pass a pointer to stack manipulation functions such as isEmpty() and isFull(), but that does not imply that you need to declare or use a pointer variable (that is indeed a noob mistake). Oftentimes, what you want is automatic or static allocation combined with use of the address-of (&) operator. Dynamic allocation should be used where it is needed, but it should be avoided where not needed. And if you don't use dynamic allocation here then there is no need for a pointer variable.

So, continuing from the declaration above:

    // use the direct member-access operator (.), not the indirect one (->)
    s.size = 80;
    s.top = -1;
    // do not cast the return value of malloc() in C:
    s.arr = malloc(s.size * sizeof(int));

    // pass the address of s to isEmpty():
    if (isEmpty(&s)) {
        printf("stack is empty");
    } else {
        printf("Not empty");
    }

    return 0;

I should not fail to mention that significant among the reasons that you don't need dynamic allocation in this case is that the struct stack does not need to live past the end of the execution of the function. If you did need it to outlive the function in which it was allocated, then dynamic allocation would be necessary to achieve that.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Yes,Sir I thought it would be easier to use pointer of struct in the struck operation functions.I used the method and got the result by just giving &s in the parameter of the function.I wanted to ask one more thing that what is the difference between s.size and s->size.Like I have to use s.size when I am not declaring to pointer as you sayed and when I was declaring it struct s a pointer I have to use s->size.Is the only difference between (.) and (->) is I can use (->) in a pointer only? –  Sep 11 '22 at 18:25
  • 1
    @Dhruv, The `.` operator is for direct access to member of a struct. The left-hand operand must designate a struct, and the right-hand operand must be the name of a member of the struct's type. The `->` is for indirect access to a struct member, via a pointer to the struct of interest. The expression `a->b` is 100% equivalent to `(*(a)).b`, which, as you can clearly see, is different from `a.b`. Never confuse a pointer with the thing to which it points. – John Bollinger Sep 11 '22 at 22:39