Why does a certain part of the code output Segmentation Fault? - c

I'm making this console application where the user has to enter inputs. However, when the code gets to the part where the user inputs a file name which then gets added into a file path using strcat, it outputs Segmentation Fault..
Here is the full code:
int main(int argc, char *argv[])
{
char theFilePath[512];
char theIP[20];
char theFile[100];
char password[1];
char username[10];
printf("Username: ");
scanf("%s" , &username);
printf("Enter password: ");
scanf("%s", &password);
printf("Enter IP: ");
scanf("%d" , &theIP);
printf("Please specify the file: ");
scanf("%s" , &theFile);
strcat(theFilePath, "./passfiles/");
strcat(theFilePath, theFile);
strcat(theFilePath,".pf");
sprintf(theFilePath,"%s",theFilePath);
if (!(file_exist (theFilePath)))
{
printf("The file cannot be found in the path %s", theFilePath);
exit(EXIT_FAILURE);
} else
{
printf("The file exists!");
}
}
Any ideas why it does that?
Thanks in advance!

You have (at least) a couple of issues.
The first is the fact that you generally shouldn't be using an unbounded %s is scanf since it does not protect against buffer overflows (very similar to gets, which was deprecated in C99 and removed from C11).
This is doubly important when your buffers are pitifully small such as char password[1] which means, with the null terminator, all your passwords will have to be zero characters long. Now I'm no world-famous security researcher but I'm reasonably confident there's a security hole there in that scheme somewhere :-)
There are far safer options when needing user input, such as the function that can be found here, one that protects against buffer overflow and provides information on (and recovers from) the user trying to enter too much data.
The second is relying on uninitialised memory. The theFilePath variable is not initialised so may contain arbitrary data in it, yet your use of strcat expects it to contain a num-terminated string. That's a bad assumption to make and can be fixed by simply making the first strcat into a strcpy or, since it's always being set to the same initial value, doing that as part of the variable declaration itself:
char theFilePath[512] = "./passfiles/";
And, as an aside, assuming you're using a modern C compiler, you would be better declaring the variables at the point where you need them, rather than all at the top of the function, meaning this declaration should go where the current (errant) strcat currently is. Localising your declaration and use greatly aids readability.
You may also want to think about the usefulness of the statement:
sprintf(theFilePath,"%s",theFilePath);
Even if it works, it's effectively a no-op since all it does is copy some data to exactly the same place as it currently exists. In any case, it's not guaranteed to work since the standard quite clearly states in C11 7.21.6.6./2:
If copying takes place between objects that overlap, the behavior is undefined.

The character array
char theFilePath[512];
was not initialized by a string. So you may not use the standard C function strcat that concatenates strings. As result the program has undefined behavior.
You could initialize it for example either like
char theFilePath[512] = "";
or like
char theFilePath[512] = { 0 };
or like
char theFilePath[512];
theFilePath[0] = '\0';
Take into account that the scanf function is not safe. It is better to use function fgets.
Also you have to write
printf("Username: ");
scanf("%s" , username);
^^^^^^^
instead of
printf("Username: ");
scanf("%s" , &username);
^^^^^^^^^
Arrays are implicitly converted (with very rare exceptions) to pointers to their first elements in expressions.

While the above answers are all helpful and correct, I would like to offer a slightly different perspective.
scanf is safe if used safely. For example,
char username[10];
scanf("%10s" , username);
is safe. Unfortunately it's not possible to pass sizeof username to scanf.
For filenames, Posix defines PATH_MAX in limits.h as the maximum valid length of a filename. If your system doesn't supply that definition, er, I recommend switching to one that does. In a crunch, MAX_PATH is available on Windows.
I also suggest looking at the man page for getopt(3). While it's useful to learn how to use scanf, it's good practice to accept command-line options for user-provided information that is needed only at startup time.
Finally, see what you can do to crank up your warning level. My recent version of clang, for example, flags your incorrect use,
$ cc -std=c11 addr.c -o addr
addr.c:9:16: warning: format specifies type 'char *' but the argument
has type 'char (*)[10]' [-Wformat]
scanf("%s" , &username);
~~ ^~~~~~~~~
1 warning generated.
Such warnings provide feedback quicker even than questions on SO. ;-)

Related

C strings keep overwriting each other

Right, so I was screwing around with C with the idea of learning the language by doing a small text based RPG game. I followed the steps of how I did the game similarly in Java but with some different workarounds until I got to the issue of getting output of having the first string being partially overwritten by the second string I was inputting. Here's the bit where the issue occurs (I presume).
struct character{
char firstname[100];
char lastname[100];
};
int main(){
struct character charname;
char first=charname.firstname[100];
char last=charname.lastname[100];
printf("And what do they call you?(First name)\n");
scanf("%s", &first);
printf("Any other names?(Last name)\n");
scanf("%s", &last);
printf("So you are called ");
printf("%s ", &first);
printf("%s ", &last);
return 0;
}
The Output I got was:
And what do they call you?(First name)
Bob
Any other names?(Last name)
Dole
So you are called BDole Dole
I am not BDole Dole but Bob Dole!!!
Any ideas?
(Just realised how horrible the code input thing here is)
When you do
char first=charname.firstname[100];
you get character 101 from an array containing 100 characters (remember that array indexes are zero-based). This alone is undefined behavior.
You then make it worse by using &first getting a pointer not into the array, not even beyond the array, but a pointer to where the local variable first is in memory, writing a string to this location will overwrite memory on the stack, and lead to very serious problems.
What you probably want is e.g.
char *first=charname.firstname;
But that isn't even needed, as arrays naturally decays to pointers to their first element, meaning this is perfectly valid:
scanf("%99s", charname.firstname);
Note the "%99s" format, which tells scanf to not read more than 99 characters, so it won't write beyond the end of the provided buffer.
This doesn't do what you think it does:
char first=charname.firstname[100];
char last=charname.lastname[100];
Probably what you meant to do was create an array[100] of char, like you would in Java with the "new" operator. But C doesn't work that way. The struct definition tells the compiler that a "struct character" has two 100-char strings in it, so when you write
struct character charname;
the space for both of those strings is reserved. In advance of needing it, on the stack. It's not initialized, but it's there and it belongs to the struct.
So you can populate those arrays now by calling scanf. Notice that no & or [] are required here; the array is said to "decay" into a pointer when used for its value.
scanf("%s", charname.first);
/* later... */
scanf("%s", charname.last);
However, it is usually smarter to use fgets() -- see this C FAQ entry.
Aside, it looks like you may be trying to learn C by taking Java-like code and modifying it haphazardly until it compiles. This does not work, especially in C. In some languages, you can get a pretty good idea of what is legal by listening to what the compiler tells you; but C has a comparatively weak type system and so it can't tell when you do something dumb.

scanf() works despite 0-length buffer and compiler warning. What is going on?

My compiler (clang) shows this message:
11:17:warning: format specifies type 'char *' but the argument has
type 'char (*)[0]' [-Wformat]
scanf("%s", &name);
~~ ^~~~~
1 warning generated.
from the following code (greetings program):
/*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[0];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", &name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
What is actually going on, and how can I fix it?
In order to understand this, you have to understand what scanf is doing. scanf in this case is reading a string from stdin, and placing it into a buffer that you give it. It does not allocate that space for you, or detect overflow. You need to allocate sufficient space for your string. As it stands now, you are allocating zero space for your string, so everything is an overflow. This is a major bug.
Say instead of char[0], you did char[40], as another user suggests.What if the user of your program writes more than 40 characters? This results in undefined behavior. Essentially, it will write to memory you don't want it to write to. It might cause a segfault, it might result in crucial memory getting overwritten, or it might happen to work. This is a weakness of scanf. Look into fgets. You tell it the size of your buffer, and input will be truncated to fit.
Of course, that has nothing to do with your warning. You're getting a warning because referring to the name of an array is the same as referring to a pointer to its first element, i.e. name <==> &(name[0]). Taking a pointer to this is like taking a pointer to a pointer, i.e. &name <==> &&(name[0]). Since scanf is looking for an argument of type char*, and it's getting a pointer to that, the type checker complains.
Your code exhibits "undefined behavior." This means anything could happen. Anything.
You are passing a zero-length array to scanf(). Also, you are not passing the array length in the format string. This results in a buffer overflow vulnerability (always, in the case of a zero-length target array).
You need something like this:
char name[51];
scanf("%50s", name);
Note the %50s now specifies the size of the target array (less one, to leave room for the null terminator!), which avoids buffer overflow. You still need to check the return value of scanf(), and whether the input name is actually too long (you wouldn't want to truncate the user's input without telling them).
If you're on Linux, check out the tool called valgrind. It is a runtime memory error detector (among other things), and can sometimes catch errors like this for you (and much less obvious ones, which is the main point). It's indispensable for many C programmers.
Just change this:
scanf("%s", &name);
to:
scanf("%39s", name);
and this:
char name[0];
to:
char name[40];
Also to you have to end it with a '\0' with:
name[39] = '\0';
Depending on how robust you want this to be you will want to reconsider the approach. I guess the first thing is whether you understand the type you are using when declaring char name[ 0 ]. this is a 'zero-sized' array of byte-sized characters. This is a confusing thing and it wouldn't surprise me if its behaviour differs across compilers...
The actual warning being complained by the compiler is that the type doesn't match. If you take the address of the first character in the array you can get rid of that (i.e. use &( name[ 0 ] ) in the scanf call). The address of name is its location on the stack - it just so happens that the array implementation uses that same location to store the array data, and name is treated differently by the compiler when used on its own so that the address of an array is the same as the address of its first element...
Using char name[ 0 ] leaves you open to causing memory corruption because there is nowhere for the string to be read, and implementation details may just luck out and allow this to work. One simple way to fix this is to replace 0 with a meaningful number which you take to the maximum length of the input string. Say 32 so that you have char name[ 32 ] instead... however this doesn't handle the case of an even longer string.
Since we live in a world of lots of memory and large stacks you can probably do char name[ 4096 ] and use 4KB of memory for the buffer and that will be absolutely fine for real world usage.
Now... if you want to be a little anal and handle pathological cases, like a user leaning on some keys whilst asleep for hours before pressing enter and adding some enormous 8000 character long string there are a few ways to handle that too with 'dynamic memory allocation', but that might be a bit beyond the scope of this answer.
As an aside, from what I understand char foo[ 0 ] is intentionally valid - it may have originated as a hack and has a confusing type, but is not uncommonly relied on for an old trick to create variable sized structs as described in this page from the GCC online docs
char name[0]; ---> char name[100];
/* You need to allocate some memory to store the name */
2.scanf("%s", &name);----> scanf("%s", name);
/* scanf takes char* as an argument so you need to pass string name only. */
i don't think that scanf("%(length - 1)s", name); is needed.
Because %s is used to reads a string. This will stop on the first whitespace character reached, or at the specified field width (e.g. "%39s"), whichever comes first.
except these don't tend to be used as often. You, of course, may use them as often as you wish!
/
*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[100];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
Because the correct way is
scanf("%s", name);
/* ^ no ampersand
and what is
char name[0];
you should specify a non-zero length and use it for scanf length specifier
scanf("%(length - 1)s", name);
/* ^ sunstitite with the value */
there were several problems with the OPs posted code
the following fixes most of them
I includd comments to indicate where the problems are
int main ()
{
//char name[0]; // this did not allow any room for the name
char name[100] = {'\0'}; // declare a 100 byte buffer and init to all '\0'
printf("-------------------\n");
printf("Write your name:, max 99 char \n"); // 99 allows room for nul termination byte
printf("-------------------\n");
//scanf("%s", &name); // this has no limit on length of input string so can overrun buffer
if( 1 == scanf("%99s", name) ) // 1) always check returned value from I/O functions
// 2) no '&' before 'name' because
// arrays degrade to pointer to array when variable
// name is used
// 3) placed max size limit on format conversion string
// so input buffer 'name' cannot be overflowed
{ // then scanf failed
perror( "scanf failed for name" );
return(-1); // indicate error
}
// implied else, scanf successful
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
return(0); // indicate success
} // end function: main
You are reading a "string", thus the correct way is:
scanf("%s", name);
Why does the compiler complain? When you provide an argument in scanf, you provide the memory location of the variable. For example:
int x;
scanf("%d", &x);
&x is int *, i.e., a pointer to an integer, so x will get the correct value.
When you read a string, you're actually reading many char variables together. To store them, you need a char * array; well, name is char * on its own, so no need to write &name. The latter is char **, i.e., a 2-dimensional array of char.
By the way, you also need to allocate space for the characters to read. Thus, you have to write char name[20] (or any other number). You also need to provide a return 0; in your int main().

The compiler shows a warning from this code [duplicate]

My compiler (clang) shows this message:
11:17:warning: format specifies type 'char *' but the argument has
type 'char (*)[0]' [-Wformat]
scanf("%s", &name);
~~ ^~~~~
1 warning generated.
from the following code (greetings program):
/*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[0];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", &name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
What is actually going on, and how can I fix it?
In order to understand this, you have to understand what scanf is doing. scanf in this case is reading a string from stdin, and placing it into a buffer that you give it. It does not allocate that space for you, or detect overflow. You need to allocate sufficient space for your string. As it stands now, you are allocating zero space for your string, so everything is an overflow. This is a major bug.
Say instead of char[0], you did char[40], as another user suggests.What if the user of your program writes more than 40 characters? This results in undefined behavior. Essentially, it will write to memory you don't want it to write to. It might cause a segfault, it might result in crucial memory getting overwritten, or it might happen to work. This is a weakness of scanf. Look into fgets. You tell it the size of your buffer, and input will be truncated to fit.
Of course, that has nothing to do with your warning. You're getting a warning because referring to the name of an array is the same as referring to a pointer to its first element, i.e. name <==> &(name[0]). Taking a pointer to this is like taking a pointer to a pointer, i.e. &name <==> &&(name[0]). Since scanf is looking for an argument of type char*, and it's getting a pointer to that, the type checker complains.
Your code exhibits "undefined behavior." This means anything could happen. Anything.
You are passing a zero-length array to scanf(). Also, you are not passing the array length in the format string. This results in a buffer overflow vulnerability (always, in the case of a zero-length target array).
You need something like this:
char name[51];
scanf("%50s", name);
Note the %50s now specifies the size of the target array (less one, to leave room for the null terminator!), which avoids buffer overflow. You still need to check the return value of scanf(), and whether the input name is actually too long (you wouldn't want to truncate the user's input without telling them).
If you're on Linux, check out the tool called valgrind. It is a runtime memory error detector (among other things), and can sometimes catch errors like this for you (and much less obvious ones, which is the main point). It's indispensable for many C programmers.
Just change this:
scanf("%s", &name);
to:
scanf("%39s", name);
and this:
char name[0];
to:
char name[40];
Also to you have to end it with a '\0' with:
name[39] = '\0';
Depending on how robust you want this to be you will want to reconsider the approach. I guess the first thing is whether you understand the type you are using when declaring char name[ 0 ]. this is a 'zero-sized' array of byte-sized characters. This is a confusing thing and it wouldn't surprise me if its behaviour differs across compilers...
The actual warning being complained by the compiler is that the type doesn't match. If you take the address of the first character in the array you can get rid of that (i.e. use &( name[ 0 ] ) in the scanf call). The address of name is its location on the stack - it just so happens that the array implementation uses that same location to store the array data, and name is treated differently by the compiler when used on its own so that the address of an array is the same as the address of its first element...
Using char name[ 0 ] leaves you open to causing memory corruption because there is nowhere for the string to be read, and implementation details may just luck out and allow this to work. One simple way to fix this is to replace 0 with a meaningful number which you take to the maximum length of the input string. Say 32 so that you have char name[ 32 ] instead... however this doesn't handle the case of an even longer string.
Since we live in a world of lots of memory and large stacks you can probably do char name[ 4096 ] and use 4KB of memory for the buffer and that will be absolutely fine for real world usage.
Now... if you want to be a little anal and handle pathological cases, like a user leaning on some keys whilst asleep for hours before pressing enter and adding some enormous 8000 character long string there are a few ways to handle that too with 'dynamic memory allocation', but that might be a bit beyond the scope of this answer.
As an aside, from what I understand char foo[ 0 ] is intentionally valid - it may have originated as a hack and has a confusing type, but is not uncommonly relied on for an old trick to create variable sized structs as described in this page from the GCC online docs
char name[0]; ---> char name[100];
/* You need to allocate some memory to store the name */
2.scanf("%s", &name);----> scanf("%s", name);
/* scanf takes char* as an argument so you need to pass string name only. */
i don't think that scanf("%(length - 1)s", name); is needed.
Because %s is used to reads a string. This will stop on the first whitespace character reached, or at the specified field width (e.g. "%39s"), whichever comes first.
except these don't tend to be used as often. You, of course, may use them as often as you wish!
/
*
* Program: gretting2.c
* Utility: Display a greeting with your name.
* Author: Adrián Garro.
*/
#include <stdio.h>
int main () {
char name[100];
printf("-------------------\n");
printf("Write your name: \n");
printf("-------------------\n");
scanf("%s", name);
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
}
Because the correct way is
scanf("%s", name);
/* ^ no ampersand
and what is
char name[0];
you should specify a non-zero length and use it for scanf length specifier
scanf("%(length - 1)s", name);
/* ^ sunstitite with the value */
there were several problems with the OPs posted code
the following fixes most of them
I includd comments to indicate where the problems are
int main ()
{
//char name[0]; // this did not allow any room for the name
char name[100] = {'\0'}; // declare a 100 byte buffer and init to all '\0'
printf("-------------------\n");
printf("Write your name:, max 99 char \n"); // 99 allows room for nul termination byte
printf("-------------------\n");
//scanf("%s", &name); // this has no limit on length of input string so can overrun buffer
if( 1 == scanf("%99s", name) ) // 1) always check returned value from I/O functions
// 2) no '&' before 'name' because
// arrays degrade to pointer to array when variable
// name is used
// 3) placed max size limit on format conversion string
// so input buffer 'name' cannot be overflowed
{ // then scanf failed
perror( "scanf failed for name" );
return(-1); // indicate error
}
// implied else, scanf successful
printf("------------------------------------\n");
printf("Hello %s, nice to meet you\n",name);
printf("------------------------------------\n");
return(0); // indicate success
} // end function: main
You are reading a "string", thus the correct way is:
scanf("%s", name);
Why does the compiler complain? When you provide an argument in scanf, you provide the memory location of the variable. For example:
int x;
scanf("%d", &x);
&x is int *, i.e., a pointer to an integer, so x will get the correct value.
When you read a string, you're actually reading many char variables together. To store them, you need a char * array; well, name is char * on its own, so no need to write &name. The latter is char **, i.e., a 2-dimensional array of char.
By the way, you also need to allocate space for the characters to read. Thus, you have to write char name[20] (or any other number). You also need to provide a return 0; in your int main().

warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘int’

So I'm new to C and am having trouble with whats happening with this warning. What does the warning mean and how can i fix it.
The code i wrote is here:
void main(void)
{
char* name = "";
int age = 0;
printf("input your name\n");
scanf("%s\n", name);
printf("input your age\n");
scanf("%d\n", age);
printf("%s %d\n", name, age);
}
The scanf function takes the address of a variable to put the result into.
Writing scanf("%d", &someVar) will pass the address of the someVar variable (using the & unary operator).
The scanf function will drop a number into the piece of memory at that address. (which contains your variable)
When you write scanf("%d", age), you pass the value of the age variable to scanf. It will try to drop a number into the piece of memory at address 0 (since age is 0), and get horribly messed up.
You need to pass &age to scanf.
You also need to allocate memory for scanf to read a string into name:
char name[100];
scanf("%99s\n", name);
The problem is this line:
scanf("%d\n", age);
scanf expects pointer arguments - this is the only way functions can modify parameters in C. In order to fix this one, you need to:
scanf("%d\n", &age);
Which passes the addressof age, which is now a pointer (a pointer is a variable containing an address to another area of memory).
As for this:
char* name = "";
Ouch-ow-please-don't! Ok, I need to explain. You've asked for a pointer to a character type, but as far as everyone's concerned, all you've got is a character, not a whole string. That's right, not enough space. Why does C let you do this? Well, C is basically portable assembler, so you can write wherever you like in memory (or rather, you can try and the compiler won't disagree, but the operating system can and probably will).
What you need to do is read up on memory allocation using malloc in order to allocate some space, otherwise I can input a massive string and it gets put at the address of name onwards.
This can, although by no means will, lead to stack-based vulnerabilities. What, stacks? Yes. A stack is a FILO structure and every time you call a function, you add space onto the stack for your return address and function arguments, as well as frequently function-scope variables.
Where this becomes a problem is if you don't check input sizes. Then, I can write massive values to your stack, including executable code... see Buffer Overflow.
So how do I mitigate this, I hear you say, just yearning not to implement software vulnerabilities? You use functions that allow you to specify your buffer input size and read into a buffer of a specific size, and go from there. That's it. That simple.
See this question: string reading in C.
You should write scanf("%d", &age), as the scanf function needs to modify the value of age, hence the need to pass it "by address" and not "by value".
It mean that it expect a "int *" (That is: A pointer to an integer) but you give it "int" which is an integer. To fix it add & to age in the scanf line so it become.
scanf("%d\n", age);
I'm assuming its complaining about the line scanf("%d\n", age); The issue is that scan f expects a pointer to your variable not the variable. You need to get an address to variable by perpending a '&` and you should be fine.
The warning means exactly what it says: the compiler expects a pointer to int rather than an int in the scanf call.
Quick fix: replace age with &age, and everything will work.
C passes all arguments by value, meaning that if you pass a variable only the value of the variable is passed. The receiving function can modify that value all it wants, but the original value isn't changed. To change the variable, you need to pass a value that points to the variable somehow, which in C is a pointer.
To get a pointer to a variable, prefix it with &. To use a variable you've got a pointer to, prefix the pointer value with *.
In this case, you want scanf to change the value of age, so you need to pass it a pointer.
char* name = "";
name points at a bit or memory large enough to hold a single null character.
scanf("%s\n", name);
You ask for a unknown number of characters to be read and stored at this address. Anything could happen. You must ensure name hass the address of a chunk of memory large enough to hold anything scanf() might read.
char twenty_bytes[20] = "";
scanf("%s\n", twenty_bytes);
hey friend recently means today I have also gone through this stuff.don't worry it's simple.
problem in the below lines of code :
scanf("%s\n", name);
and
scanf("%d\n", age);
you simply written these lines like printf() function. if you are using the scanf() function then always use ampersand(&) before the variable in the scanf() function because it's necessary. & is the 'Address of ' operator, it gives the location of the number(address) used by the variable in memory.
your corrected lines of code:
scanf("%s\n", &name);
and
scanf("%d\n", &age);
Next time when you are going to writting this type of code or using scanf() function always try to keep in mind this stuff due to that you will not get the problem in your code.
Thank you for asking the question due that I also will not make such a mistake in the future while writing such type of code.

Using an ampersand in scanf()

When I compile scanf("%s", &var);, gcc sends back a warning:
warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
however when I compile scanf("%s", var);, no warning is applied. Both pieces of code work and the book I am reading specifically says to use the ampersand, but even it doesn't in some of the examples.
My question is, should I continue to use the ampersand, even when the book doesn't specify?
From what you've posted var is a char array. In that case, you don't need the ampersand, just the name var will evaluate to a (char *) as needed.
Details:
scanf needs a pointer to the variable that will store input. In the case of a string, you need a pointer to an array of characters in memory big enough to store whatever string is read in. When you declare something like char var[100], you make space for 100 chars with var[0] referring to the first char and var[99] referring to the 100th char. The array name by itself evaluates to exactly the same thing as &var[0], which is a pointer to the first character of the sequence, exactly what is needed by scanf. So all you need to do is scanf("%s", var);, but be aware that scanf does not enforce size constraints on input strings, so if the user inputs a 101 length string your will have a buffer overrun, which will result in bugs or, even worse, security problems. The better choice is generally fgets which does allow size constraints for input strings.
I invite any other answerers to give a good summary of pointers and references here. I don't think I can do that without making some mistakes here and there, and I have no intent to deal with the nerd rage that will follow.
So I'll just point you to a good resource to learn about pointers and references which lies at the heart of your problem. http://www.cplusplus.com/doc/tutorial/pointers/
Remove the & from the scanf("%s", &var); so it is scanf("%s", var);.
When you use an array like this one:
char name[20];
you must consider that a memory area composed by 20 chars is associated with it. To obtain the address of the beginning of that memory area you must use the name of the array, while to obtain the address of a single char of that array, you have to use a sintax like this: &name[i].
You are using scanf to read a string, which is an array of char in C. scanf require the address of the memory area associated to the type of variable to read. In this case, you are reading an array so you have only to use the name.
If you want to read a single variable and not an array you have to use the ampersand. For example:
char myChar;
scanf("%c", &myChar);
I hope this can be helpful.

Resources