I'm currently trying to wrap my head around pointers in C, coming from front-end developing this not an entirely easy endeavour. I'm following this tutorial, and everything is running smoothly until I try to compile the following example:
#include <stdio.h>
int main(int argc, char *argv[]) {
int **ramon;
int *paul;
int melissa = 5;
paul = &melissa;
ramon = &paul;
printf("ramon = %d\n", ramon); // <- warning: format '%d' expects type 'int'...
printf("&paul = %d\n", &paul); // <- warning: format '%d' expects type 'int'...
printf("*ramon = %d\n", *ramon); // <- warning: format '%d' expects type 'int'...
printf("&melissa = %d\n", &melissa); <- warning: format '%d' expects type 'int'...
printf("**ramon = %d\n", **ramon);p1); <- warning: format '%d' expects type 'int'...
return(0);
}
From the first printf line I get this error: "warning: format '%d' expects type 'int', but argument 2 has type 'int **'"
I reckon this has to do with the way I initialize my pointers, but standing at the bottom of a steep learning curve I don't know how to progress. What is wrong, how do I initialize pointers to avoid the warnings?
Your pointer initialization looks correct. The problem is that you are trying to print a variable of type int** (i.e. a "pointer to a pointer to an int") using the %d format specifier which is for int values.
Print int value
If you want to print the value of melissa (i.e. 5) which is essentially what ramon is indirectly pointing to, you need to de-reference the pointer value the correct number of times.
De-referencing pointers is done via the * operator, and it essentially means "the value at which this pointer is pointing to".
De-referencing it once (i.e. *ramon) will get the int* value which ramon is pointing to.
De-referencing it a second time will get the int value which the de-referenced int* value is pointing to.
You can chain together de-reference operators like so to get what you want:
printf("ramon = %d\n", **ramon);
Print pointer value
If you want to print a pointer (i.e. memory location) value, you can use the %p format specifier. This will print the memory address out in hex:
printf("ramon = %p\n", ramon); // Print the "pointer to the pointer to melissa"
printf("ramon = %p\n", *ramon); // Print the "pointer to melissa"
ramon isn't an int, it's a pointer to a pointer to an int. **ramon would be an int. You're trying to print a bunch of ints with %d, but you're mostly trying to print pointers which uses the format %p.
read man printf. It is not clear whether you want to print the value pointed to by ramon or the actual value of ramon which is an address of an pointer to an int. Same for other warnings as well.
The type of the expression ramon is an int **, and the %d specifier expects an int. *ramon will be of type int *, and **ramon will be the desired int.
If you want to print the pointer itself, use the %p specifier.
ramon and paul are pointers and the printf format specifier for printing values of pointers themselves (not what they're pointing to) is %p. Try
printf("ramon = %p\n", ramon);
The warning has nothing to do with how you are initializing your pointers, it has to do with the mismatch in types between printf's %d specifier and the types you are passing to it.
If you want to print a pointer, use %p.
You declared ramon of type "pointer to pointer to type int". i.e. it holds an address to a "pointer to type int". %d on the other hand is the format specifier for int which is why you are getting the errors. Instead try the following:
printf("&paul = %p\n", ramon); //print the address that ramon points to
printf("&melissa = %p\n", *ramon); //print the address that paul points to
printf("&melissa = %p\n", paul); //same as above
printf("melissa = %d\n", **ramon); //print the contents of melissa
printf("melissa = %d\n", *paul); //same as above
printf("melissa = %d\n", melissa); //same as above
Output
&paul = 0xbf8072f4
&melissa = 0xbf8072f0
&melissa = 0xbf8072f0
melissa = 5
melissa = 5
melissa = 5
I reckon this has to do with the way I initialize my pointers
Why would you reckon that when the error message says nothing about initialization? Read it again:
"warning: format '%d' expects type 'int', but argument 2 has type 'int **'"
You have %d in the format string for your printf() call, as a placeholder for the value that you want to print. %d is used as a placeholder for values that are int s. The value you want to print is ramon. That variable has the type int**. The type int and the type int** are not the same.
If you want to print a pointer, then you should write the format string so as to expect a pointer. We format pointers with %p.
but standing at the bottom of a steep learning curve I don't know how to progress.
The way to progress is to read the error and/or warning messages and attempt to understand them. The error messages are talking about types. You should not be trying to do anything with pointers if you haven't first got your head around the concept that values have a type (i.e., what kind of thing they are).
Related
I am currently doing pointers. I have been programming for a long time, but not in C/C++. With that being said, my pointer knowledge is abysmal.
Currently, I am following a guide on YouTube and he prints the code below.
int main() {
int a = 5;
int *p;
p = &a;
printf("%d\n", p);
}
This prints successfully for him, and he sees a memory location. For me, I see the error
warning: format '%d' expects argument of type 'int', but argument 2 has type 'int *'
From this, I expect I need to put an & in front of the p to make it print the value. But then I receive this error,
int main() {
int a = 5;
int *p;
p = &a;
printf("%d\n", &p);
}
'int', but argument 2 has type 'int **'
Where is the hole in my knowledge? Any key tips or strategies when working with this, I don't know why I find this so abstract.
Thanks,
I was expecting the value to print as expected, but instead am greeted with the error.
%d is the wrong format specifier for pointers. That may work on a more lenient or noncompliant implementation, but you should use %p to print pointer values.
Warnings are not errors. You're receiving a warning, which is not stopping your program from working, because the print specifier %d (ie printf("%d")) is for displaying integers, and you're giving it a non-integer argument of type int*.
The problem here is not with the argument, it's with the print specifier. Your attempt at a fix just changes the int* to an int**, which still does not match the format specifier %d. Use %p instead, which is the specifier for pointers, and will fix the warning, and print the address in hexadecimal notation.
You could also suppress the warning with a series of explicit casts from int* to int, but integer representations of memory addresses are generally much less used than hexadecimal representations in the first place.
Note that using wrong format specifier in printf() lead to undefined behaviour1).
The correct format specifier to print a pointer is %p format specifier.
Remember, format specifier %p expect that the argument shall be a pointer to void, so you should type cast pointer argument to void *. The correct statement to print pointer p would be:
printf("%p\n", (void *)p);
C11#7.21.6.1p9 [emphasis added]
9 If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
int array[2][3] = {{2,3,6},{4,5,8}};
printf("%d\n",*array);
What will be the output of this and please explain how?
Regards,
Winston
Educate yourself on multidimensional arrays.
Array array is a 2D array:
int array[2][3] = {{2,3,6},{4,5,8}};
*array is the first element of array array because
*array -> * (array + 0) -> array[0]
The first element of array array is array[0], which is {2,3,6}. The type of array[0] is int [3].
When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule).
So, in this statement
printf("%d\n",*array);
*array will be converted to type int *. The format specifier %d expect the argument of type int but you are passing argument of type int *. The compiler must be throwing warning message for this. Moreover, wrong format specifier lead to undefined behaviour.
If you want to print a pointer, use %p format specifier. Remember, format specifier %p expect that the argument shall be a pointer to void, so you should type cast pointer argument to void *.
This call of printf
printf("%d\n",*array);
invokes undefined behavior because there is used incorrect conversion specifier %d with a pointer expression.
If you will write instead
printf("%p\n", ( void * )*array);
then there will be outputted the address of the extent of memory occupied by the array that is the address of the first element of the array.
That is the expression *array has the type int'[3]. Used as an argument in the call of printf it is implicitly converted to pointer to the first element of the type int *. It is the same as to write
printf("%p\n", ( void * )&array[0][0]);
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
I'm learning about pointers, and I'm running this program from the tutorial that gives some interesting output.
#include <stdio.h>
int main () {
int var = 20; /*actual variable declaration */
int *ip; /*pointer variable declaration*/
ip = &var; /*store addres of var in ip variable*/
printf("Address of var variable: %x\n", &var);
/*address stored in ip variable*/
printf("Address of stored in ip variable: %x\n", ip);
/*access the value using pointer */
printf("value of *ip variable: %x\n", *ip);
return 0;
}
And to my understanding, the site says my output should be Two matching memory locations, and the value of 20 for the "Value of *ip variable" part. I have no issue with the memory locations, they both come up as the same just as one would assume however, the last part, its telling me the value of the *ip variable is 14?
Address of var variable: 6d73b8cc
Address of stored in ip variable: 6d73b8cc
value of *ip variable: 14
Whats going on here? Compiled with gcc, which gives one warning about format %x expects an unsigned integer but argument 2 has type of....
MorePointers.c:10:9: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("Address of var variable: %x\n", &var);
^
MorePointers.c:13:9: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("Address of stored in ip variable: %x\n", ip);
Correct me, please, if I am wrong, but could it be due to the format, which when expecting an unsigned integer could cause the number to be one other than 20? being an unsigned integer is within values 0 to 65,535 or 0 to 4,294,967,295, while an integer is within values -32,768 to 32,767 or -2,147,483,648 to 2,147,483,647?
What's happening is that you've printed the integer value 20 as a hexadecimal value, which rightly is displayed as 14. I suspect you were expecting 20 decimal. :)
Some fixes :-
printf("Address of var variable: %x\n", &var);
This is incorrect, a pointer should be printed as a pointer value
printf("Address of var variable: %p\n", &var); /* << ensure pointer value */
When you call printf, it mixes fixed text with parameters in order...
printf( "hello %d world %d today %d\n", 1,2,3 );
Prints hello 1 world 2 today 3
The way a parameter is displayed is based on the format specifier.
%s /* displays as a string */
%d /* displays as an integer in normal decimal */
%x /* displays an integer in hexa-decimal. */
%f /* displays as a floating point */
%p /* displays a pointer address */
Decimal goes 0,1,2,..,8,9,10,11,...,14,15,16,17,...,20
Hexadecimal goes 0,1,2,..,8,9, A, B,..., E, F,10,11,...,14
You are printing the hexadecimal value of var or *ip, which is 0x14.
Use %d for decimal value.
The first two printf() statements have undefined behaviour, as %x requires the corresponding parameter to be of type unsigned, not a pointer. Hence the warnings. Look up the %p format if you want to print the value of pointers (and convert the pointers to (void *) to use that).
%x prints the value in hex, base 16. The value of 20 (decimal) in hex is 14 (1*16 + 4). Strictly speaking, you should convert an int to unsigned to use %x.
printing addresses with printf() should be done with '%p' not '%x'.
If you compiled with all the warnings enabled (for gcc, at a minimum use: -Wall -Wextra -pedantic )
then the compiler would have told you, for line 10 and line 13:
warning: format: '%x' expects argument of type 'unsigned int', but argument two has type 'int*' [-Wformat=]`
The last call to printf() is passing a type of 'int' but the '%x' is expecting a unsigned int.
suggest declaring 'ip' and 'var' as unsigned int rather than int
or change the last printf() to:
printf("value of *ip variable: %d\n", *ip);
you can read.learn about the format specifiers for printf() at:
<http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output>
or reading the printf man page
This question already has answers here:
format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[64]
(3 answers)
Closed 9 years ago.
I got a warning in my program, and it says:
format '%c' expects argument of type 'char *' , but argument 2 has type 'char (*)[10]' [-Wformat]
Here's my program:
#include<stdio.h>
int main()
{
char array[10];
scanf("%10c", &array);
printf("%.10s", array);
return 0;
}
The warning disappears when I remove '&' from scanf.
I know, it's an array and doesn't require &. But don't they have same effect?
I mean both '&array' and 'array' give address of its first element, right?
If so, what's the difference here?
I read some related questions here, and googled a lot.
It has been said that '&array' is a pointer to an array of characters if 'array' is an array while 'array' itself is a pointer to char.
According to what it says, since I'm using %c, a pointer to an array of characters should be passed, I think.
Idk, I would very greatful if someone explains how %[width]c works.
I also verified that all 'array', '&array' and '&array[0]' give address of its first element.
Here's what I did:
int main()
{
char array[10];
puts("ADDRESS:");
printf(" %p \n %p \n %p", array, &array, &array[0]);
return 0;
}
If they all give same address, why is it giving such warnings?
It also works for %s.
They all work fine in most of windows compiler, without any warnings.
Since I'm a windows user, I never used gcc compiler before. And what I was thinking was it's just not mandatory to write & as with function pointers.
You don't necessarily have to write & with function pointers, I read.
I'm getting more and more confused, please help me get it.
Thank you.
array and &array both yield a pointer to the same address, but with different types. The former is equivalent in most situations to &array[0], a char * in your case. &array, however, is the address of the array itself, which has type char (*)[10] in your example.
array and &array are not the same... even if they have same address location in it.
array here being char array, it points to a single char, and if you increment it increases by 1 char size.
but &array points to the entire array and if increments it increases by the array size.
scanf function expects for the array.. not &array