2

I was trying to solve this problem

When i create a char * and pass it into scanf:

char* input = "";
scanf("%s", input);

It behaves weirdly.
However, when i change the definition and initalize 1000 chars to \0:

char input[1000] = { '\0' };

It behaves properly. Why is it that way?

Soft Waffle
  • 356
  • 1
  • 12
  • 1
    Dupe: [Why do I get a segmentation fault when writing to a string initialized with "char \*s" but not "char s\[\]"?](https://stackoverflow.com/questions/164194/why-do-i-get-a-segmentation-fault-when-writing-to-a-string-initialized-with-cha) – Marco Bonelli May 14 '20 at 18:42

2 Answers2

7

I'm guessing you're seeing a segmentation fault. When you declare char* input = "";, you're causing input to be a pointer directed at a string literal. String literals are stored in a read-only section of memory. Therefore, trying to overwrite the data with scanf is an invalid use of memory.

However, when you declare char input[1000];, you've now got an array on the stack, which is a section of memory which can be written to. That's why that code works.

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
2

First question is what does this declare?

char* input = "";

That's a single byte in a non-mutable (read-only) area of memory. If you write anything to it, that's undefined behaviour, or something more colloquially described as weird behaviour.

When you re-write it correctly you get a 1000 character buffer and you can read to it without undefined behaviour, provided your input is < 1000 characters.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • 1
    can i make it dynamically change the size of the string? And if i can, is it worth it? – Soft Waffle May 14 '20 at 18:28
  • 2
    Also isn’t that (usually?) in read-only memory since it’s a string literal so writing to it would cause issues? – Sami Kuhmonen May 14 '20 at 18:28
  • 1
    @SamiKuhmonen A good point. Some compilers refuse to treat this as mutable, so yeah, it has to be `const char* input = ""` instead. I've seen many that just don't care, or at least don't unless told to with particular compiler flags, and let the undefined behaviour spill forth unimpeded. – tadman May 14 '20 at 18:29
  • @tadman so if i want to initalize it, should i instead use `char* input = { '\0' };`? – Soft Waffle May 14 '20 at 18:31
  • Still no. You need to have a buffer *of sufficient length for the input*. That creates a one byte buffer again, which is inadequate, and it's also a pointer to read-only memory. `char input[BUFFER_SIZE]` is a better approach where `#define BUFFER_SIZE 1024` is defined elsewhere. You *must* keep track of your buffer sizes, and you really should declare the size when writing to them, like `scanf("%1024s", &input)`, though honestly `scanf` is something you should stop using as quickly as possible as it severely limits what you can do. – tadman May 14 '20 at 18:34
  • One of the biggest problems in C is *buffer overflow bugs* caused by losing track of, or incorrectly allocating buffers. These kinds of bugs will utterly ruin you unless you have a strong command of what you're supposed to do, and what you're supposed to *not* do. Here's [how to use `scanf` correctly](https://stackoverflow.com/questions/1621394/how-to-prevent-scanf-causing-a-buffer-overflow-in-c). – tadman May 14 '20 at 18:35
  • 7
    This is completely wrong. That's a **string literal**. Trying to write through a pointer to a string literal is undefined behavior, no matter the size. Also, no, it doesn't have to be `const`. *"Some compilers refuse to treat this as mutable"* - it's the standard that dictates so, any compliant compiler will refuse to treat it as mutable, since it's UB. – Marco Bonelli May 14 '20 at 18:36
  • 2
    `scanf("%1024s", &input)` is also wrong if the `input` buffer size is `1024`, you should `scanf("%1023s", &input)` instead. – Marco Bonelli May 14 '20 at 18:49
  • @MarcoBonelli Yes, that's correct. I got held up trying to find out how to inject that constant in there without leaning too hard on the pre-processor, but got distracted and gave up. – tadman May 14 '20 at 18:50
  • Please at least correct your answer: *"That's a single byte. If you write anything more to it, that's undefined behaviour"* - this is wrong, that's not the reason writing there is bad. Furthermore, you are implying that string literals can be modified, which is wrong. The reason why OP's code is wrong is that trying to modify a string literal is undefined behavior *regardless* of the size. – Marco Bonelli May 14 '20 at 19:08
  • @MarcoBonelli Corrected phrasing. – tadman May 14 '20 at 19:17