scanf() (C Language ) confused me - c

When do I need to insert/don't insert & for scanf() in C? Thank you.
int main()
{
char s1[81], s2[81], s3[81];
scanf("%s%s%s", s1, s2, s3);
// If replace scanf() with the expression below, it works too.
// scanf("%s%s%s", &s1, &s2, &s3);
printf("\ns1 = %s\ns2 = %s\ns3 = %s", s1, s2, s3);
return 0;
}
//programming is fun
//
//s1 = programming
//s2 = is
//s3 = fun

scanf puts the scanned values in the address pointed by it's arguments. The & is the address operator, and it's used to take the address of a variable.
But, you are using arrays, and arrays are downgrade to pointers when used as functions arguments. So, you don't need to use the & operator in the case of arrays.
Example:
char s[81];
int n;
int* nptr;
//Initialize nptr to some meaningful value
scanf("%s %d %d",s,&n,nptr);
In this case, we need to use the & operator to get the address were n is kept. We don't need to use it with nptr, because it is already a pointer to someplace in the memory, neither with s, because an array gets downgrade to a pointer when it's passed to a function.

The arguments after the format specifier must be pointers. When an array name is passed to a function, the location of the initial element is passed, so you don't need to use the & at all in your example. You could do this though (from K&R):
int day, year;
char monthname[20];
scanf("%d %s %d", &day, monthname, &year);
Since day and year are int, you must use the & to get the address of those variables. Since monthname is an array, no & is required.

In C, when you are dealing with arrays:
int c_array[24];
c_array == &c_array == &c_array[0]
Yeah, its funny - they look the same (the difference is in the types). Read this.

From the comp.lang.c FAQ: I thought you always needed an & on each variable passed to scanf.
I highly recommend reading the rest of the comp.lang.c FAQ.

s1 returns the address of the first element of the array, while &s1 returns the address of the array itself. The address of the first element and the address of the array itself are identical, hence why both representations work.

Just a guess, but I'd assume it's because s1, s2, and s3 are arrays.

If a is an array, both a and &a result in a pointer in this context:
a does due to the array decaying to a pointer (C99, §6.3.2.1/3):
Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
... emphasis added
&a does as a result of the & operator - it returns a pointer to the object.

Scanf accepts variable number of parameters. first argument of scanf is format and after that n addresses where values to be stored while n is the number of format specified in format string. since you are using array, to store values you have to provide base address of the array.
//If int
int i;
scanf("%d",&i); // store int value at address &i
float f;
scanf("%f",&f); //store float value at address &f
int a[10];
scanf("%s",a); //store string or array value at a
if using a in last line confuses you, you can try the same thing with address of first element which is &a[0].
Hope it helps,
GG

Generally, you would use scanf the way you do in your uncommented line. The way C arrays work, is the name of arrays like s1, s2, and s3 is actually the address of the first element of the array. For any primitives though, you would have to use the &variable syntax. For example:
float f;
scanf("%f", &f);

Related

Need an explanation in which occasions we should use & with printf in C

As far as I know in c when using printf() we don't use &.Right?But in my programme, if I don't use it in the display function it gives me an error.Can someone explain this? Thank you
#include<stdio.h>
#define max 100
void enqueue();
char dequeue(void);
int front=-1,rear=-1,option;
char name[max][max],val;
void display(void);
void enqueue() {
printf("Enter the name of the paitent : ");
if(rear==max-1)
printf("Line is full");
else if (front==-1 && rear==-1)
front=rear=0;
else
rear++;
scanf("%s",&name[rear][rear]);
}
char dequeue(void) {
char val;
if(front==-1 || front >rear )
printf("Line is empty");
else
{
val=name[front];
front++;
if(front>rear)
front=rear=-1;
return val;
}
}
void display(void) {
int i;
if(front==-1|| front >rear)
printf("The queue is empty");
else
{
for(i=front; i<=rear; i++) {
printf("%s\t",&name[i][i]);
}
}
}
int main () {
printf("\n\n*******Medical Cneter********");
printf("\n\t1. Insert a paitent");
printf("\n\t2. Remove a paitent");
printf("\n\t3. Check Paitent list");
printf("\n\t4. Display");
printf("\n\t5. Exit");
do {
printf("\nEnter your option: ");
scanf("%d",&option);
switch(option)
{
case 1:
enqueue();
break;
case 2:
dequeue();
break;
// case 3:
case 4:
display();
break;
}
} while(option !=5);
}
If I don't use & the programme will crash. As far as I know in c when using printf() we don't use. But in my programme, if I don't use it in the display function it gives me an error.Can someone explain this? Thank you
To answer your question, let's review what the & operator does, and what types of values we need to pass to printf, and also, for comparison, what types of values we need to pass to scanf.
If you have a thing x, then the expression &x gives you a pointer to x. If x is an int, &x gives a pointer-to-int. If x is a char, &x gives pointer-to-char.
For example, if I write
int i;
int *ip;
ip = &i;
I have declared an int variable i, and a pointer-to-int variable ip. I have used the & operator to make a pointer to i, and I have stored that pointer-to-int in the variable ip. This is all fine.
As you may know, when you call scanf you always have to pass pointers to the variables which you want scanf to fill in for you. You can't write
scanf("%d %d", x, y); /* WRONG */
because that would pass the values of the variables x and y to scanf. But you don't want to pass values to scanf, you want scanf to read some values from the user, and transmit them back to you. In fact, you want scanf to write to your variables x and y. That's why you pass pointers to x and y, so that scanf can use the pointers to fill in your variables. So that's why you almost always see &'s on the arguments in scanf calls.
But none of those reasons applies to printf. When you call printf, you do want to pass ordinary values to it. You're not (usually) asking printf to pass any data back to you. So most of the printf format specifiers are defined as accepting ordinary values, not pointers-to-values. So that's why you hardly ever see &'s in printf calls.
Now, you might think of & as an operator that "converts things" to pointers, but that's not really a good way of thinking about it. As I said, given an object x, the expression &x constructs a pointer to x. It doesn't "convert" anything; it certainly doesn't "convert" x. It constructs a brand-new pointer value, pointing to x.
In the code you posted, it looks like you might have used & in an attempt to perform such a "conversion". You had an array name of type array-of-array-of-char, or a two-dimensional array of characters. You were trying to print a string with %s. You knew, or perhaps your compiler warned you, that %s needs a pointer-to-char, and you knew (or your compiler told you) that the expression name[i][i] gave a value of type char. Now, putting a & in front of name[i][i] did indeed get a value of type pointer-to-char, as %s requires, and it might even have seemed to work, but it's a pretty haphazard solution.
It's true that printf's %s needs a pointer-to-char, but it doesn't need just any pointer-to-char; it needs a pointer-to-char that points to a valid, null-terminated string. And that's why, even though %s needs a pointer, you still don't usually see &'s in printf calls. You could use & on a single character variable to get a pointer to that character, like this:
char c = 'x';
printf("%s", &c); /* WRONG */
But this is broken code, and won't work properly, because the pointer you get is not to a valid string, because there's no null termination.
In your code, you probably want to change the line
printf("%s\t",&name[i][i]);
to
printf("%s\t",name[i]);
name is a two-dimensional array of char, but since a string in C is an array of char, you can also think of name as being a (single dimensional) array of strings, and I think that's how you're trying to use it.
Similarly, I suspect you want to change the line
scanf("%s",&name[rear][rear]);
to
scanf("%s", name[rear]);
But before you say "I thought scanf always needed &!", remember, the rule is that scanf needs a pointer. And since name[i] is an array, you automatically get a pointer to its first element when you pass it to scanf (or in fact when you use it in any expression). (And this is also the reasoning behind printf("%s\t",name[i]).)
If you wanted to use an explicit &, what you want is a pointer to the beginning of the string array you want scanf to fill in, so I think you'd want
scanf("%s", &name[rear][0]);
instead of the expression you had.
(It looks like you were, probably accidentally, running your strings down the diagonal of the name array, instead of down the left edge. It's also curious that you declared the perfectly square array
char name[max][max];
that is, 100 strings of 100 characters each. It's not wrong, and it'll work, but it's curious, and it makes it easier to mix up the rows and the columns.)
`
I tried compiling your code and it seems I'm getting the error:
warning: assignment makes integer from pointer without a cast [-Wint-conversion]
val=name[front];
^
The reason is that name is a 2D array and you are assigning a pointer to a 1D array of chars to a char.
I think that in order to fully understand the problem one would have to understand how C deals with memory and pointers.
The '&' symbol means that you are taking the address of something (not to be confused with c++ references).
This means that if a function has an argument like the following:
void foo(char* bar);
and you want to pass your variable char var; to the function, you would have to call the function using the '&' symbol to explicitly tell the compiler that you want to pass the address of var as the parameter to the function.
foo(&var);
if you want to access the value of var inside function foo you would have to "dereference" the pointer so that the compiler understands that you want the value stored at the address you just passed to the function.
In order to dereference a pointer you use the '*' symbol.
char some_char_in_foo = *var;
I suggest reading up on pointers to clarify the matter further.
The %s conversion specifier in both printf and scanf expects it's corresponding argument to have type char *, and to point to the first character in a string.
Remember that in C, a string is a sequence of characters including a 0-valued terminator. Strings are stored in arrays of char (or wchar_t for "wide" strings).
Your name array can store max strings, each of which can be up to max-1 characters long, not counting the string terminator.
When an array expression is not the operand of the sizeof or unary & operators, or isn't a string literal used to initialize a character array in a declaration, the expression is implicitly converted ("decays") from type "array of char" to "pointer to char", and the value of the expression is the address of the first element.
name has type "max-element array of max-element array of char". This means that each name[i] has type "max-element array of char", which, if it's not the operand of & or sizeof, "decays" to type char *.
That's basically a long-winded way of saying that the expression max[i] is equivalent to &max[i][0]. So you can write your printf statement as
printf( "%s\t", name[i] );
Similarly, you can rewrite your scanf statement in the enqueue function as
scanf( "%s", name[i] );
although honestly, for user input it's safer to use fgets:
if ( fgets( name[i], sizeof name[i], stdin ) )
// successful input
else
// EOF or error on read
The & operator means "take the reference of". scanf modifies its arguments, therefore, you need to given a reference to the arguments you want modified. printf does not modify its arguments, therefore, you can pass its arguments by value, because it can do its job with a copy.
However, this is not a final rule, as the format string %p will print a pointer (i.e a reference). So printf might need a reference to a variable in some cases.
A more general rule would be this one: scanf takes its arguments by reference, printf takes its arguments by value.

Assign pointer type to string type

I'm expecting a compile error , taking into account that a pointer has to be assigned in %p, but the codes below doesn't give me error when i intentionally assign a pointer to %s. By adding an ampersand &, by right it should generate the address of the array and assign the memory address into %p, instead of giving the value of the string. Unless I dereference the pointer, but I don't dereference the pointer at all, I never put an asterisk * in front of my_pointer in printf.
#include <stdio.h>
int main()
{
char words[] = "Daddy\0Mommy\0Me\0";
char *my_pointer;
my_pointer = &words[0];
printf("%s \n", my_pointer);
return 0;
}
please look at this :
printf("%s \n", my_pointer);
My understanding is , *my_pointer (with asterisk *)should give me the value of the string.
But my_pointer (without asterisk) shouldn't give me the value of the string, but it should give me only the memory address,but when I run this code, I get the value of string eventhough I didn't put the asterisk * at the front. I hope I'm making myself clear this time.
Here:
printf("%s \n", my_pointer);
%s, expects a char* and since my_pointer is a char* which points to an array holding a NUL-terminated string, the printf has no problems and is perfectly valid. Relevant quote from the C11 standard (emphasis mine):
7.21.6.1 The fprintf function
[...]
The conversion specifiers and their meanings are:
[...]
s - If no l length modifier is present, the argument shall be a pointer to the initial
element of an array of character type. 280) Characters from the array are
written up to (but not including) the terminating null character. If the
precision is specified, no more than that many bytes are written. If the
precision is not specified or is greater than the size of the array, the array shall
contain a null character.
[...]
IMO, You are being confused here:
taking into account that a pointer has to be assigned in %p, but the codes below doesn't give me error when i intentionally assign a pointer to %s
First of all, %s, %p etc are conversion specifiers. They are used in some functions like printf, scanf etc.
Next, you are the one specifying the type of the pointers. So here:
my_pointer = &words[0];
&words[0] as well as my_pointer is of type char*. Assigning these two is therefore perfectly valid as both are of the same type.
The compiler is treating your code exactly as it is required to.
The %s format specifier tells printf() to expect a const char * as the corresponding argument. It then deems that pointer to be the address of the first element of an array of char and prints every char it finds until it encounters one with value zero ('\0').
Strictly speaking, the compiler is not even required to check that my_pointer is, or can be implicitly converted to, a const char *. However, most modern compilers (assuming the format string is supplied at compile time) do that.
In c, array name is also pointer to the first element, means in your case words and &words[0] when as a pointer, they have the same value.
And, you assign it to another pointer of the same type, so this is legal.
About string in c, it's just an array of chars ending with '\0', with its name pointer to the first char.

What exactly is a variable name in C?

The value of an array name is the address of the start of (zeroth element) the array; therefore, the & is not necessary.
Ex:
scanf("%s", string1);
Then what is the value of the integer or character variable names which we have to use & operator? Not addresses like array names I hope. What are they? This is confusing.
Ex:
scanf("%d", &number1);
What is number1 exactly? Is it an address too?
The value of an array name is the address of the start of(zeroth element) the array
No, it isn't. It's just that arrays can decay into a pointer to their first element in certain conditions (when passed to a function or assigned to a pointer, for example).
therefore, the & is not necessary. !!!!!!!
Writing 7 exclamation marks is not necessary either. Note that if arr is an array, then arr and &arr are not the same at all (as you migh assume). arr is of type T [N] where T is the type of an element in the array, and N is the number of elements. The type of &arr, however, is a "pointer-to-array-of N items of type T" (T (*)[N]). This difference is important (not only) because pointer arithmetic will yield in different results on a pointer-to-T and on a pointer-to-array-of-T.
Then what is the value of the integer or character variable names which we have to use & operator? Not addresses like array names I hope.
No, not like arrays (because they are not arrays), but & still is the addressof operator. &variable gives a pointer to the variable, of which the type is T *, if the type of variable was T.
In this specific case, you claimed that number1 was an int, so &number1 is an expression of type int *.
What is number1 exactly? Is it an address too?
Based on your type modifier, number1 is presumably an int, but of course we don't know that for sure because you're not telling us. If I understand correctly what you're asking, number1 is an integer and &number1 is a pointer to that integer.
Then what is the value of the integer or character variable names?
The value of an unmodified variable name is the value of that variable. Arrays are a special case, as you noted. Array names are not actually variables. Given:
int a[10];
int *pa;
you can legally do this:
pa = a;
but not this:
a = pa;
a is the name of an array, not a variable.
Update: For those who think it's weird to say that an array name is not a variable, I was practically quoting the second edition of The C Programming Language by Kernighan and Ritchie. (Ritchie was the creator of C.) Now I'll quote them directly, from page 99 of the second edition:
A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.
Oh my, you do indeed have a lot to learn about C. But perhaps the confusion is mostly about arrays & pointers. For practical purposes, an array variable is just a pointer. Realistically, it's not -- its type is indeed an array, but it is implicitly converted to a pointer of the type it is an array of. I hope that helps.
If you declare number1 and give it some value:
int number1;
number1 = 1234;
then &number1 is the address of the memory location where the variable is stored. If you peek into that memory location, you will find it holds 1234, the value of the variable.
If array_of_numbers is declared as:
int array_of_numbers[100];
then the first number in the array is array_of_numbers[0], the address of the first element in the array is &array_of_numbers[0].
array_of_numbers is exactly the same thing as &array_of_numbers[0].
the scanf("%d", &number1); expects address(es) where to put the variable(s), if you did
number1=1234;
scanf("%d", number1);
the scanf function will get whatever number it parses for %d, and try to stuff it into memory location 1234, which is not what you normally want.
See , If you declared it like:
int number1;
Then &number1 is basically the location which will store the contents of number1.
so, when you write :
scanf("%d"&number1);
The compiler stores whatever number you input into the location specified by &number1.So,'&number1'
is somewhat the address where the contents of number1 will stored.
Next time you want to use the contents of number1,they will be picked up from the memory location specified by &number.
I'd like to mention this example:
int a,b,c;
scanf("%d %d ",&a,&b);/*&a and &b are just locations assigned to a and b, in which we store integers*/
c=a+b;
At,c=a+b,here a and b will represent the integers you stored in the memory locations assigned to them ,but c will represent the memory location assigned to c,NOTICE:that there is no &operator infront of c,we just use & operator in function like scanf which are input/output functions defined in stdio.h .
When you declare int number1;
number1 can represent an address too,for eg:
when you write number1=4; here number1 represent the memory location . because you are storing 4 into it.

Behaviour of scanf() [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
confusion in scanf() with & operator
Why we need a & in scanf for inputting integer and why not for characters.
Do the & in scanf refers to merory location while getting input.
Eg:-
main()
{
int a;
char c;
scanf("%d",&a);
scanf("%c"c);
}
For each conversion specifier, scanf() expects the corresponding argument to be a pointer to the proper type: %d expects an argument of type int *, %f expects an argument of type double *, %c and %s both expect an argument of type char *, etc.
The difference between %c and %s is that the former tells scanf() to read a single character and store it in the location specified by the corresponding argument, while the latter tells scanf() to read multiple characters until it sees a 0-valued character and store all those characters in the buffer starting at the location specified by the argument.
You need to use the & operator on your arguments if they are not already of pointer type. For example:
int x;
int *px = some_valid_memory_location_such_as_&x;
char c;
char *pc = some_valid_memory_location_such_as_&c;
...
scanf("%d", &x); // x is not a pointer type, so we must use the & operator
scanf("%d", px); // px is a pointer type, so we don't need the & operator
scanf("%c", &c); // etc.
scanf("%c", pc); // etc.
Where things get confusing is reading strings of characters (using the %s conversion specifier):
char buf[SIZE];
scanf("%s", buf); // expression 'buf' *implicitly* converted to pointer type
Why don't we need the & operator in this case? It has to do with how C treats array expressions. When the compiler sees an expression of array type (such as buf in the scanf() call), it will implicitly convert the expression from type N-element array of T to pointer to T, and set its value to the address of the first element in the array. This value is not an lvalue -- it cannot be assigned to (so you can't write something like buf = foo). The only exceptions to this rule are when the array expression is an operand of either the sizeof or & operators, or if the array expression is a string literal being used to initialize another array:
char *p = "This is a test"; // string literal implicitly converted to char *,
// string *address* written to p
char a[] = "This is a test"; // string literal not implicitly converted,
// string *contents* copied to a
In short, the expression buf is implicitly converted from type char [SIZE] to char *, so we don't need to use the & operator, and in fact the type of the expression &buf would be pointer to SIZE-element array of char, or (*)[SIZE], which is not what scanf() expects for the %s conversion specifier.
The ampersand symbol is required in both cases. scanf requires pointers (you were probably thinking of char* or char[] - they are pointers themselves).
Scanf reads input to a memory address. a is the value held by a. &a is the location of a in memory.
In your code above, the c should be &c.
Because scanf() needs pointers, and &a is the pointer to an integer.
In your example, you need a comma and an ampersand in front of the c.
int main(void)
{
int a;
char c;
char s[21];
scanf("%d",&a);
scanf("%c", &c); // Fixed!
scanf("%20s", s);
printf("a = %d, c = %c, s = <<%s>>\n", a, c, s);
}
If you were reading a string, you would pass the string - a pointer to char - to scanf().
You need to provide scanf with pointer, that's why you have & in scanf("%d",&a);
. scanf("%c"c); will not work at all.
Your example is wrong. If you have a
char c;
then you need to add an & to the name when calling scanf:
scanf("%c", &c);
However, if your variable is already a pointer, for example because it is a char[] (which is a fancy syntax for pointers), you have to omit the &.
I like to think of the ampersand (&) as "address of". So you'd read &a as "address of a".
Also, I tried compiling this but it warned me on gcc:
Warning: format "%c" expects type 'char *', but argument 2 has type 'int'
Which is true, since a char is basically an int.

Why does scanf() need & operator (address-of) in some cases, and not others? [duplicate]

This question already has answers here:
What is array to pointer decay?
(11 answers)
Closed 1 year ago.
Why do we need to put a & operator in scanf() for storing values in an integer array but not while storing a string in a char array?
int a[5];
for(i=0;i<5;i++)
scanf("%d",&a[i]);
but
char s[5]; scanf("%s",s);
We need to pass in the address of the place we store the value, since array is a pointer to first element. So in the case with int/float arrays it basically means (a+i).
But whats the case with strings?
scanf accepts a pointer to whatever you are putting the value in. In the first instance, you are passing a reference to the specific int at position i in your integer array. In the second instance you are passing the entire array in to scanf. In C, arrays and pointers are synonymous and can be used interchangeably (sort of). The variable s is actually a pointer to memory that has contiguous space for 5 characters.
When you use the name of an array in an expression (except as the operand of sizeof or the address-of operator &), it will evaluate to the address of the first item in that array -- i.e., a pointer value. That means no & is needed to get the address.
When you use an int (or short, long, char, float, double, etc.) in an expression (again, except as the operand of sizeof or &) it evaluates to the value of that object. To get the address (i.e., a pointer value) you need to use the & to take the address.
All the variables used to recieve values through scanf() must be passed by their addresses. This means that all arguments must be pointed to the variables used as arguments.
scanf("%d", &count);
Stings are read into character arrays, and the array name without any index is the address of the first element of the array.So to read a string into a character array address, we use
scanf("%s",address);
In this case address is already a pointer and need not to be preceded by the & operator.
scanf("%d", a + i ) works too.
%d and %s just tell scanf what to expect but in both cases it expects an address
in C, arrays and pointers are related.
%s just says to scanf to expect a string which is \0 terminated, whether it will fit into the character array or not scanf doesn't care.
Because characters arrays are already pointers.
You can think of C arrays as pointers to a stack-allocated amount of RAM. You can even use pointer operations on them instead of array indexing. *a and a[0] both produce the same result (returning the first character in the array).

Resources