Printing pointed value from passed pointer - c

I am confused as to why this code succesfully gives me back the right input.
#include <stdio.h>
#include <stdlib.h>
int bintest();
int main()
{
int* x = malloc(sizeof(int));
printf("\n\n*****\nEnter value of x\n*****\n");
scanf("\n%d", &x);
bintest(x);
}
int bintest(int* y)
{
printf("\ny: %d", y);
}
Why doesnt it work when I print **y, I assume pointer x is passed to bintest and stored in pointer y, which then should be called **y to print the value of the input?

You should start turning on compiler warnings and paying attention to them. Your short snippet yields 3! warnings.
$ gcc main.c -Wall -Wextra
main.c: In function ‘main’:
main.c:12:19: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int **’ [-Wformat=]
scanf("\n%d", &x);
~^ ~~
main.c: In function ‘bintest’:
main.c:18:23: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("\ny: %d", y);
~^ ~
%ls
main.c:19:5: warning: control reaches end of non-void function [-Wreturn-type]
}
^
You program has undefined behavior, and this can manifest itself by working as it should.
The correct code should be
scanf("\n%d", x);
...
printf("\ny: %d", *y);
And declare bintest as a void function if you don't want to return anything.
I am confused as to why this code succesfully gives me back the right input.
You're storing the read value in the pointer x which creates a memory leak since you throw away the malloc call. You could remove the malloc call and your program would behave the same. (Probably. It does have undefined behavior).

It's undefined behaviour.
It happens to work for following reason:
&x is the address of the x pointer. As the size of a pointer is usually at least the size of int, scanf("\n%d", &x); simply overwrites the pointer. Then you pass that pointer (whose value is now what the user typed in) to bintest
Your compiler should have given you at least two warnings such as:
'scanf' : format string '%d' requires an argument of type 'int *', but variadic argument 1 has type 'int **'
'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'int *'
These two warnings are rather errors and you should not ignore them.

You did NOT store the value of an integer in x IF that is what you wanted; you asked user for an input and overwrote the pointer x with user provided value. That pointer x now points to whatever the user gave.
Later you pass that x into that function and print that value: so you get what the user provided.
However your CANNOT de reference it. The x is pointing to a user provided value. What value is that? Do you know that it is some valid memory location.
Best read help documentation on scanf.
IF you really wanted to store an integer x with user provided value the code goes like
int x;
scanf(... &x).
Then you pass &x to that function.

Supporting what #Jabberwocky said,
test.c: In function ‘main’:
test.c:7:12: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int **’ [-Wformat=]
7 | scanf("\n%d", &x);
| ~^ ~~
| | |
| | int **
| int *
test.c: In function ‘bintest’:
test.c:11:16: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
11 | printf("\ny: %d", y);
| ~^ ~
| | |
| int int *
| %ls
test.c:12:1: warning: control reaches end of non-void function [-Wreturn-type]
12 | }
| ^
This came up when I tried to compile the code with CLion IDE (gcc (GCC) 9.1.1 20190503 (Red Hat 9.1.1-1), C11) although even I don't understand it fully. I hope it helps and someone could explain it further.

If you want to scan a value to where x is pointing, then use x like this: scanf("\n%d", x). To print the value that you just placed, then pass in x like this: bintest(x);, but print *y like this: printf("%d", *y);
scanf("\n%d", &x); is the same as x = scan;
scanf("\n%d", x); is the same as *x = scan; which is what you want.
So in this example scanf("\n%d", &x); you give scanf &x, which is the address to x itself. Doing this means scanf will change the value of x, thus changing what x is pointing to.
The function scanf wants an address to where it puts its value. So to put it where x is pointing to, you should just pass in x.
The reason the values you have are the same is because you are simply passing in x like this: bintest(x); and printing y like this: printf("%d", y);. In this example, y is just a copy of x.
If you want to test out how these functions are working with pointers try using this code. I entered in 99 as an example.
#include <stdio.h>
#include <stdlib.h>
int bintest();
int main(){
int* x = malloc(sizeof(int));
printf("value of x: %d\n",x);
printf("address of x: %d\n",&x);
printf("value at %d: %d\n", x, *x);;
printf("\n\n*****\nEnter value of x\n*****\n");
scanf("\n%d", x);
printf("value of x: %d\n",x);
printf("address of x: %d\n",&x);
printf("value at %d: %d\n", x, *x);
bintest(x);
}
int bintest(int* y){
printf("\ny: %d", *y);
}
You should get an output similar to this:
value of x: 7018424
address of x: 6422316
value at 7018424: 7017768
*****
Enter value of x
*****
99
value of x: 7018424
address of x: 6422316
value at 7018424: 99
y: 99

Related

Can someone explain why this program behaves like this?

I have the following program in C:
void main() {
int x[3];
int* p = &x;
printf("%d %d \n", p, x);
}
those values for p and x seem to be the same, but i dont understand why, since p is the address of pointer x, shouldn't there be something like *p = x instead of p = x ?
Your code produce some warning at compilation time :
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int *’ [-Wformat=]
and your compiled code cause an undefined behaviour and the equal result is due to the Undefined behaviour.
Tips:
Your code is wrong conceptually, please read more on pointer, array e type in C language.
The big problem is that p and &x are different types.
The pointer given by &x is a pointer to the whole array x, not to a single element, and its type is int (*)[3], not int *.
If you want to get a pointer to the first element of x then use &x[0], or plain x (as that decays to &x[0]).
And even while the types of &x and &x[0] are different, they both point to the same location (as your (invalid) printouts indicates). This can be seen if you attempt to visualize the array x in memory:
+------+------+------+
| x[0] | x[1] | x[2] |
+------+------+------+
^
|
&x
|
&x[0]
As I already mentioned in a comment, to print pointers you need to use the %p format specifier. Mismatching formatting specifier and argument type leads to undefined behavior.
What's more, the %p format specifier is for void * pointers, so you need to cast the pointers (unless they are already void * of course):
printf("%p %p \n", (void *) p, (void *) x);
There are several issues in your program leading to undefined behaviour.
First, array x is not initialized, and accessing it later leads to UB.
Second, x when used as pointer is already the address of the first element of array x (equivalent to &x[0]); Hence &x would be a pointer to that pointer.
Third, %d requires an integral value, not a pointer to one; so you need to dereference p and x.
The following program should behave as you expect:
int main() {
int x[3] = { 1,2,3 };
int* p = x;
printf("%d %d \n", *p, x[0]);
}

Format specifier int * warning message

I wrote simple C program with scanf & printf like:
int n;
scanf("%d", &n);
int result = 7 - n;
printf("%d", &result);
and got this warning message:
warning: format '%d' expects argument of type 'int', but argument 2
has type 'int *' [-Wformat=]
printf("%d", &result);
I dont understand why argument 2 has type int * instead of int? How can I solve this?
result is a integer variable. If you want to print its value then use %d format specifier & provide the argument as only result not &result.
This
printf("%d", &result);
replace with
printf("%d", result);
If you want to print the address of result variable then use %p format specifier.
printf("%p", &result); /* printing address */
Edit : %p format specifier needs an argument of void* type.
So to print the address of result cast it as void*. for e.g
printf("%p", (void*)&result); /* explicitly type casting to void* means it works in all cases */
Thanks #ajay for pointing that, I forgot to add this point.

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

Each time I submit a program on hackerrank the following error occurs.
solution.c: In function ‘main’:
solution.c:22:14: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%d", &sum);
It would be very helpful if someone could tell me what this means?
I assume that you have declared sum as an int. So the correct call to printf is :
printf("%d", sum);
as %d specifier means that you are going to print an int, but you are passing the int's address, which is a pointer to int, or int *.
NOTE : Do not confuse printf with scanf, as the second does require a pointer. So, for reading variable sum, you would use :
scanf("%d", &sum);
but for printing, the correct way is without &, as written above.
If you want to print the address of sum you can use printf( "%p", &sum )
Int is a primitive, primitives are data stored in memory. each data chunck is set in a specific memory block, those blocks has "memory addresses" that refer to them.
If you define int i = 1 your computer allocates an integer in memory (in a block, with a memory address f.e. 0xF00000) and sets its value to 1.
When you refer to this integer as i, you are accessing the value stored in 0xF00000, that happen to be 1.
In C you can also get the i reference (the memory address it's allocated in) by prefixing it with & (ampersand), by doing this you will get the memory address of the variable rather than its value.
i === 1; // true
&i === 1; //false
&i === 0xF00000; //true
This memory address can be assigned to a pointer (a variable that 'points' to a memory address, thus, have no it's own value) so it can be accessed directly too dereferencing it so you can gather the value inside that memory block. This is achieved using *
int i = 1; //this allocates the
int *ptr = &i; //defines a pointer that points to i address
/* now this works cause i is a primitive */
printf("%d", i);
/* this works also cause ptr is dereferenced, returning the
value from the address it points, in this case, i's value */
printf("%d", *ptr);
In your example, you are passing a reference to printf (printf asks for a value and is receiving a memory address) so it doesnt work.
Hope this helps you understand C and pointers better
#include<stdio.h>
int main(){
int var = 10;
int* a = &var;
printf("%d", a);
return 0;
}
First i Used "%d" and it shows error that format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’
then I replace "%d" with "%p" and it Works.
#include<stdio.h>
int main(){
int var = 10;
int* a = &var;
printf("%p", a);
return 0;
}
you have to use "%p" to print address of a variable. Thank you

Variable Initialization Bug?

So I declared a variable as an integer and initialized it to 0. When I tried printing the value of that variable, it gave me an incredibly high number. int
x=0;
printf("%d", &x);
This is what I did. Am I doing anything wrong? Thanks in advance.
The operator '&' represent the address of that variable. we need, the actual value of that variable use like this...
printf("%d",x);
When we are using the &x, it will refer the address of the x . we need to print the value of x then use this,
printf("%d", x);
In scanf() function, only we need to use &x, to locate the memory address to store the value.
You print the address of the x so it will print the address during the compile time it will display the warning
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat]
So use following
printf("%d",x);
Please print the value of X instead address like printf("%d",x);

Using printf with a pointer to float gives an error

When I try to compile this code:
void main()
{
float x;
x=6.5;
printf("Value of x is %f, address of x %ld\n", x, &x);
}
it gives me this error:
pruebaso.c: In function ‘main’:
pruebaso.c:5:9: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
printf("Value of x is %f, address of x %ld\n", x, &x);
^
pruebaso.c:5:9: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘float *’ [-Wformat=]
I've seen in another forum the solution is to make a cast to a void pointer first:
http://www.linuxquestions.org/questions/programming-9/beginning-c-programming-how-to-print-memory-locations-printf-conversion-number-927305/
But making this change,
printf("Value of x is %f, address of x %ld\n", (double)x, (void *)&x);
now gives me a warning:
pruebaso.c: In function ‘main’:
pruebaso.c:5:9: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
printf("Value of x is %f, address of x %ld\n", (double)x, (void *)&x);
^
pruebaso.c:5:9: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘void *’ [-Wformat=]
Could someone explain me how could I solve it without getting a warning?
Thank you
You need to include <stdio.h> to suppress the first warning and use a cast to void * and use %p to suppress the second warning.
In C90, using printf() without <stdio.h> invokes undefined behavior because the implicit declaration will not match the actual declaration, since printf() is variadic. (Using fputs() would be okay, by comparison.) In C99, implicit declarations are not allowed but GCC allows you to compile such code anyway.
#include <stdio.h>
int main(void)
{
float x = 6.5;
printf("Value of x is %f, address of x %p\n", x, (void *) &x);
}
The %p format specifier is used for printing pointers. Technically, it must be used with a char * or void * pointer. On modern systems, this will not affect the result; but passing other pointer types to %p will technically invoke undefined behavior (which is bad).
The %ld format in your code is wrong, even though it will work on most systems. First, it takes a long argument, which requires a cast (even though the cast will only make a difference on a few systems). Second, even if you add the cast, not all information in the pointer is guaranteed to remain (it might chop off bits or do something else). In practice, 64-bit Windows systems are the only systems where a cast to long chops of bits and the cast works fine everywhere else.
So use %p and cast to void *.
void main()
{
float x;
x=6.5;
printf("Value of x is %f, address of x %ld\n", x, &x);
}
The immediate problem is that you're missing the required #include <stdio.h>, but that's not the only problem with your code. Some of these things are errors that you can probably get away with (compilers may not complain, and may generate code that does what you expect), but there's no reason not to do it right.
#include <stdio.h>
int main(void)
{
float x;
x = 6.5;
printf("Value of x is %f, address of x %p\n", x, (void*)&x);
}
To explain the changes I made:
#include <stdio.h> is required for any program that calls printf. More precisely, a declaration of printf is required, and <stdio.h> provides it. (In principle you could write your own declaration instead, but there's no good reason to do so.)
The correct definition of main is int main(void). void main() may be accepted by some compilers, but it's useful mostly as a way to detect bad books. If you're using a book that tells you to use void main(), its author does not know the language very well, and may have given you other misinformation. Find a better book. (Caveat: void main(), or more likely void main(void) might actually be the preferred implementation-defined form for some embedded systems. but you're probably not using such a system.)
The "%ld" format requires an argument of type long int. The only correct format for printing a pointer value is "%p". Since "%p" requires an argument of type void*, you should explicitly cast your pointer value to void*. Omitting the cast is likely to "work", but float* and void* are distinct types, and are not guaranteed to have the same representation or to be passed to functions in the same way.
C implicitly declares functions if you use them before defining it, which caused the error " incompatible implicit declaration of built-in function ‘printf’".
To fix this, add #include <stdio.h> at the top of the file (this copies over the header file that includes a declaration for printf.
The second thing issue is that you should use %p to print pointers.
The resulting code is
#include <stdio.h>
int main(void)
{
float x;
x=6.5;
printf("Value of x is %f, address of x %p\n", x, (void *) &x);
return 0;
}

Resources