0

Here if I comment out both the dynamic memory allocation lines the code does not work whereas it works fine if both the lines are included . Why?

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

int main()

{
    struct data
    {
        char *a; 
        char *b;
    } p;

    printf("\n%lu\n", sizeof(struct data));

    // p.a=(char *)malloc(1);
    // p.b=(char *)malloc(1);

    printf("Enter a string ::");
    scanf("%s", p.a);
    printf("Enter another string ::");
    scanf("%s", p.b);

    printf("\n%s", p.a);
    printf("\n%s", p.b);

    return 0;
}
Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
Nishant
  • 1
  • 4

1 Answers1

0

You either need to statically allocate storage for the scanf captured string or dynamically. In any case you need to ensure scanf does not capture more than what you allocated for.

Static allocation:

#define MAX_STRING 64
struct data_stat
    {
        char a[MAX_STRING]; 
        char b[MAX_STRING];
    } p;

or dynamically as you started to do:

struct data_dyn
{
    char *a; 
    char *b;
} ;
...
struct data_dyn p;
p.a = (char*) malloc(MAX_STRING*sizeof(char));

Then you need to ensure scanf strictly capture MAX_STRING-1 chars at max. Last char of a string in C is always \0. In both data_stat and data_dyn the field a and b contain a (char*) address stored on 4 bytes (pointer). What differs is the "range" covered by the array pointed to by the pointer. In data_stat the allocated memory is part on the data_stat structure itself, in data_dyn the allocated memory is on the heap.

See here for scanf details: Read no more than size of string with scanf()

Jean-Marc Volle
  • 3,113
  • 1
  • 16
  • 20
  • See if I used a character pointer(which has a size of 4 bytes )then why do i need to initialize it again – Nishant Jan 04 '22 at 14:29
  • why wouldn't that be use rather than declaring it dynamically – Nishant Jan 04 '22 at 14:29
  • `scanf` write into memory at the adress you provide (`p.a`). It writes as many chars as the user enters. You need to allocate enough storage for that many chars. – Jean-Marc Volle Jan 04 '22 at 14:31
  • a pointer just stores the base address – Nishant Jan 04 '22 at 14:31
  • so a character pointer should just store the base address of the string . – Nishant Jan 04 '22 at 14:32
  • Pointer is the base address, the scanf write at base_add, base_add+1, base_add+2,.... You need to reserve those "addresses" upfront – Jean-Marc Volle Jan 04 '22 at 14:32
  • why don't i have to do that if i use char pointer outside a structure – Nishant Jan 04 '22 at 14:35
  • outside a structure it works properly without any dynamic memory allocation – Nishant Jan 04 '22 at 14:36
  • Not it does not work either. You are writing anywhere in memory. This kind of code will crash eventually. You can check it by declaring `char *a,*b,*c,*d ; scanf(...,d); scanf(...,a)` You will see that d content is overwritten by a. – Jean-Marc Volle Jan 04 '22 at 14:43
  • Yes ,it crashes for more pointers but works for a single pointer – Nishant Jan 04 '22 at 14:44
  • but i still can't understand how you mean to say pointers allocation work – Nishant Jan 04 '22 at 14:45
  • please help me sir – Nishant Jan 04 '22 at 14:48
  • https://www.programiz.com/c-programming/c-dynamic-memory-allocation – Jean-Marc Volle Jan 04 '22 at 14:51
  • The `(char*)` before `malloc` is useless. Don't teach this bad habit. – Jabberwocky Jan 04 '22 at 15:45
  • malloc returns a void pointer type so it has be casted . shouldn't it be like that? – Nishant Jan 04 '22 at 15:54
  • Hello @Jabberwocky. I tend to disagree on your comment. See here why: https://wiki.sei.cmu.edu/confluence/display/c/MEM02-C.+Immediately+cast+the+result+of+a+memory+allocation+function+call+into+a+pointer+to+the+allocated+type – Jean-Marc Volle Jan 04 '22 at 16:35
  • @Nishant no. Void pointer are safely promoted to any other pointer type. – Jabberwocky Jan 04 '22 at 16:36
  • @Jean-MarcVolle I tend to disagree too. Taking the example on the link you provided: `p = malloc(sizeof(gadget));` should be written `p = malloc(sizeof(*p));`: no cast needed, no error possible. – Jabberwocky Jan 04 '22 at 16:40
  • @Jabberwocky I simply referenced the CERT (C Secure Coding Standard) whose scope is described here: https://wiki.sei.cmu.edu/confluence/display/c/Scope and is applicable to C11. I agree that your proposal addresses the risk of misalignment between allocated size and actual pointed variable type though ;-) – Jean-Marc Volle Jan 04 '22 at 17:37