简体   繁体   中英

Wrong int outputted?

#include <stdio.h>
int main(){
    int age;
    char name[] ="";
    printf("enter your age: ");
    scanf("%d", &age);
    printf("enter your name: ");
    scanf("%s", &name);
    printf("your name is %s and you are %d years old.",name, age);

    return 0;
}

If i for example set the age to "20" and the name to "name", it outputs the following:

your name is name and you are 6647137 years old.

Why does it say "6647137" years instead of 20?

在此处输入图像描述

char name[] ="";

You do not define name correctly.

#define MAX_NAME_LENGTH 100
char name[MAX_NAME_LENGTH+1]; 

Defining it incomplete and completing it afterwards you make it point to some region where there may be other variables aound the array defining the string literal, or the string literal can be even in RO memory, making it impossible to write. It is undefined behavior trying to write at the pointer of a string literal (6.4.5.p6 String literals, page 63).

You overwrite beyond the much too short array of chars for name .
It currently is of size 1, holding exactly only the teminating '\0' .
Your weird age value can in many environment be explained by the integer being the first victim.

Make sure to use an array of sufficient size.
Also it is very much recommended to use advanced features of scanf() to avoid buffer overrun.

Please read the documentation:
https://en.cppreference.com/w/c/io/fscanf

And this article might be very helpful:
http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html

Learn this soon and learn this well: C does not have a first-class "string" type!

When you wrote

char name[] = "";

you did not declare a string variable, that initially contained an empty string, but that could and would automatically expand to contain any string you tried to assign to it.

No, what you got was an array of char of size exactly 1, initially containing the empty string, consisting of exactly (and only) the string-terminating character '\0' . This array can't be used for much of anything: the only thing it's ever going to be able to contain is the empty string, because it doesn't (and will never) have room for anything more.

In C, it is generally your responsibility to know how big your strings are going to be, and to explicitly allocate each variable to refer to enough memory for any string it might contain.

For example, you could write

char name[11] = "";

Now what you're saying is, "Give me an array of characters, sufficient to contain strings up to 10 characters long (plus 1 for the terminating \0 character), initially containing the empty string."

Now you can safely say

scanf("%s", name);

But there are two more points to make.

First, you'll notice that I have left out the & . You might have gotten the impression that you always need the & on your variables when you call scanf . And that's a real rule, but it has an exception: it turns out that you do not need the & when you're using %s to read a string into an array. Sometimes the error is innocuous (the code will happen to work anyway), but sometimes it will cause problems (such as when you use %s to read into an array pointed to by a pointer variable). My compiler warns me warning: format specifies type 'char *' but the argument has type 'char (*)[1]' when I do something like this.

But second, if we've declared

char name[11] = "";

, then how do we actually enforce that? How do we arrange that we, or a function like scanf over which we have less control, won't accidentally try to write more than 10 characters to our name array?

As we've already seen, if you just call

scanf("%s", name);

you don't get any protection. scanf will read as many characters as the user types, until it sees a newline or other whitespace, and it will write all those characters to the variable you provided, and if that's more characters than the variable can hold, boom, something bad happens.

One way of protecting against this is to give scanf a limit on the number of characters it can read:

scanf("%10s", name);

Now, by putting that 10 in there, you're telling scanf not to read a string longer than 10 characters, so it won't overflow your name array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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