Basic C Pointers - c

For some reason when I try to compile this code in the C program it is giving me back an error. I am trying to print out the actual memory address of variable x. If anyone knows I would appreciate it!
Code:
int x = 7;
printf("x is %d\n", x);
x = 14;
printf("x is %d\n", x);
int *aptrx = malloc(sizeof(int));
aptrx = &x;
printf("aptrx is %x\n", aptrx);
Error:
*pointer.c:12:29: error: format specifies type 'unsigned int' but the argument has type* 'int \*' [-Werror,-Wformat]

You do not need to have this line in your code if you just want to print the address of x.
int *aptrx = malloc(sizeof(int));
You do not need to allocate memory whenever you create a pointer variable. If you want to point to an existing variable, which you want in this case, you can simply do
int *aptrx = &x;
Then try to print the address using below line using the format specifier %p.
printf("aptrx is %p\n", aptrx);

You are having an error because the format expects an unsigned int but the argument is an int *.
The manual for printf says about the %x conversion specifier:
The unsigned int argument is converted [...] to unsigned hexadecimal (x and X)
notation.
If you want to print a pointer, you can use the %p conversion specifier.
The void * pointer argument is printed in hexadecimal (as if by %#x
or %#lx).
Like this:
printf("aptrx is %p\n", aptrx);

It's not necessary to allocate memory dynamically to create a pointer variable.
int *aptrx = malloc(sizeof(int)); //unnecessary
Simply, create a pointer variable just like any other variable
int *aptrx = &x;
To print out the value of the pointer (i.e. address of x), use the format specifier %p or %u:
printf("aptrx is %p\n", aptrx);

Related

Why it becoming an error when we declare an integer pointer variable as integer variable?

If a pointer "p" holds the address of a variable "a". if a=12 ( just taking an integer ) . If the address of "a" is 1024 (just an assumption for asking my doubt). That means the value in "p" is 1024. This 1024 is address but it is basically a number . Then why it doesn't work when we declare the integer pointer variable "p" as integer variable "p". like:
int p, a=12;
p=&a;
printf("value of a is : %d", *p );
The example could be properly written (with some additional output) as:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
intptr_t p;
int a = 12;
p = (intptr_t)(void *)&a;
printf("value of a at %" PRIdPTR " is : %d\n", p, *(int *)(void *)p);
return 0;
}
That relies on the following facts:
A pointer to any object can be converted to void * and back to a pointer to the original object type and it will compare equal to the original pointer to the object (so it will still point to it).
A pointer to void can be converted to a intptr_t or a uintptr_t value (by a cast operator) and back again and it will compare equal to the original pointer.
The PRIdPTR macro defined by #include <inttypes.h> expands to a string literal containing a printf conversion specifier (possibly preceded by a length modifier) suitable for printing the value of a parameter of type intptr_t as a signed decimal number. It is being included in the printf format string by string literal concatenation.
A void * pointer value is usually printed using the %p printf format, for example:
printf("value of a at %p is : %d\n", (void *)p, *(int *)(void *)p);
or:
printf("value of a at %p is : %d\n", (void *)&a, a);
To declare p as a pointer to int do it the following way:
int *p; /* p is a pointer to int */
so, with initializers:
int a = 12, /* a is an integer var and it's initialized to 12 */
*p = &a; /* p is an integer pointer and it's initialized to the addreess of a */
or as assignments:
a = 12; /* a is assigned the value 12 */
p = &a; /* p is assigned the address of a */
works, and *p will have the same value as a.
printf("value of a is : *p==%d (or what should be the same: a==%d)", *p, a);
*p means the to take data from the place which p stores.
The * operator when applied to an operand p basically means "read what's on address stored in p and interpret it as the type indicated by the pointer type p is declared as"
You're missing the last part. In your case, p is not a pointer, so the dereference operator does not make sense to use.

Output address of variable without printf %p

I am a first year student in C programming so my skill/knowledge is limited. I am trying to create my own implementation on printf, but I am having trouble with retrieving and printing the address of a variable. With printf, its possible to output the address of a variable with %p, i need to replicate %p somehow.
When storing the address of a variable, the data type is int*, and I cannot figure out how to write this address to the screen(stdout).
For Example:
int i = 123;
int *address = &i;
Now how would I output address(not the value at i)? I have tried using the original printf format specifiers for testing purposes. I tried using %x, %s, %d, %lu... it all gives me an error as I am trying to output an int*(integer pointer).
Can anyone assist me in outputting the address?
You can only inspect the bits of the pointer and print those, using the type unsigned char:
unsigned char* a = ( unsigned char* )address;
for( size_t i = 0 ; i < sizeof( address ) ; i++ )
printf( "%hhu" , a[i] );
Another option, if the pointer is a pointer to an object, is to cast the pointer to types: intptr_t or uintptr_t, but the availability of those types is implementation defined.
If it's for the address of an object you could do the following:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
int a;
uintptr_t uip = (uintptr_t) ((void*) &a);
printf("address of a = 0x%"PRIXPTR, uip);
}
To print the address of a function you need to go as proposed here.

Why does the C program give me this output when printing a pointer?

#include <stdio.h>
int main()
{
int i;
int buf[10];
char *p ;
p = 4;
printf("%d",p);
return 0;
}
Output:
4
How come it is 4? I was expecting some address value. Can you please help me understand it?
This is undefined behavior, because %d expects an integer.
The reason why you see this output is that pointers have enough capacity to store small integer numbers, such as 4. If by coincidence the pointer size on your system matches the size of an integer, printf would find a representation that it expects at the location where it expects it, so it would print the numeric value of your pointer.
The proper way to print your pointer would be with the %p format specifier, and a cast:
printf("%p", (void*)p);
I was expecting some address value.
You would get an address value if you had assigned p some address. For example, if you did this
char buf[10];
char *p = &buf[3];
printf("%p", (void*)p);
you would see the address of buf's element at index 3.
Demo.

What is the meaning of printf("%p", int 1)?

I'm trying to understand the difference between int a and int *a, my first step was to see the value I could get by printi %p of an int a. Of course the compiler shows warnings, but does complete the job for the following code.
#include <stdio.h>
int main() {
int a;
printf("a - declared");
printf("int a = [%d]\n", a); // example - 1745899614
printf("int a pointer = [%p]\n", a); // example - 0x6810505e
a = 10;
printf("a - initialized to value of 10\n");
printf("int a = [%d]\n", a); // exmaple - 10
printf("int a pointer = [%p]\n", a); // example - 0xa
return 0;
}
And as I've mentioned in the source code, I do get a somewhat satisfactory result of 0xa which is equal to 10 in hexadecimal for the value of %p of an int a. But is it actually the case that int points to to that address, or is this just the compiler trying to make sense of %p in such a case?
Where is the memory allocated for ints? How do I test for that?
To print the address of an object named a, use:
printf("The address of a is %p.\n", (void *) &a);
Merely using %p does not tell printf to print the address of the object you use as the argument. You must use the “address of” operator, &, to take the address. Otherwise, you are passing the value of a to printf, not the address of a.
Additionally, it is proper to convert the address to void *, as shown above, because the %p specifier expects a pointer to void. Other types of pointers often work (or appear to work) in many C implementations, but the technical requirement is that a pointer to void be passed.
I imagine the formater ( in printf ), is just interpreting the memory as it is told to. So yeah, "%p" is for pointer, but you gave it an int. You wanted to give it the address of a:
printf( "%p", &a );
for the whole shabang:
int a = 10;
int *b = &a;
printf("value of a: %d\n", a );
printf("location of a: %p\n", &a );
printf("value of b: %p\n", b );
printf("location of b: %p\n", &b );
printf("dereference b: %d\n", *b );
But is it actually the case that int points to to that address, or is
this just the compiler trying to make sense of %p in such a case?
It's the latter. Compiler tries to interpret the integer as a pointer. When you print the value of a using %p compiler finds that the type of a is int and warns you that it's not a pointer.
To print the address of a use:
printf("int a pointer = [%p]\n", (void*)&a);
If a is a pointer (e..g int *a;) then you need to initialize it with a valid address and then you can print:
printf("int a pointer = [%p]\n", (void*)a);
%p is merely a way to tell printf to print your value as an address memory. You're passing the value of 10to it (the value of a) and you get printed this value in the hexadecimal notation 0xa. There is no special interpretation, it is just a formatting option.
If you want the value of the a's address memory printed you can simply do printf("%p", &a);. &a is the address of a.
Or if you want to use a pointer:
int* p;
p = &a;
printf("%p", p); //Prints the p value, that is the a address. Equivalent to printf("%p", &a).

How does the scanf function work in C?

Why do you require ampersand (&) in the scanf function. What will the output or type of error (compile or runtime) be in the following C code?
#include <stdio.h>
void main() {
int a;
printf("enter integer:");
scanf("%d", a);
}
The & in C is an operator that returns the address of the operand. Think of it this way, if you would simply give scanf the variable a without the &, it will be passed to it by-value, which means scanf will not be able to set its value for you to see. Passing it by-reference (using & actually passes a pointer to a) allows scanf to set it so that the calling functions will see the change too.
Regarding the specific error, you can't really tell. The behavior is undefined. Sometimes, it might silently continue to run, without you knowing scanf changed some value somewhere in your program. Sometimes it will cause the program to crash immediately, like in this case:
#include <stdio.h>
int main()
{
int a;
printf("enter integer: ");
scanf("%d",a);
printf("entered integer: %d\n", a);
return 0;
}
Compiling it shows this:
$ gcc -o test test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘int’
And executing shows a segmentation fault:
$ ./test
enter integer: 2
Segmentation fault
In C, all function arguments are passed by value; any changes to the function's formal parameter are not reflected in the actual parameter. For example:
void foo(int bar)
{
bar = bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(x);
printf("x after foo = %d\n", x);
return 0;
}
The output of the program will be
x before foo = 0
x after foo = 0
because bar receives the value of x (0), not a reference to x itself. Changing bar has no effect on x.
In C, the way around this is to pass a pointer to a variable:
void foo(int *bar)
{
*bar = *bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(&x);
printf("x after foo = %d\n", x);
return 0;
}
Now the output of the program is
x before foo = 0
x after foo = 1
This time, the formal parameter bar is not an int, but a pointer to int, and it receives the address of x (given by the expression &x in the call to foo), not the value contained in x. The expression *bar means "get the value in the location bar points to", so *bar = *bar + 1 corresponds to x = x + 1.
Since scanf() needs to write to its arguments, it expects those arguments to typed as pointers. The "%d" conversion specifier expects the corresponding argument to be a pointer to int (int *), the "%u" conversion specifier expects a pointer to unsigned int (unsigned *), "%s" expects a pointer to char (char *), "%f" expects a pointer to float (float *), etc. In your example, since a is typed int, you need to use the expression &a to get a pointer.
Note that if a were already a pointer type, you would not need to use the & operator in the call to scanf():
int main(void)
{
int a, *pa; // declare pa as a pointer to int
...
pa = &a; // assign address of a to pa
scanf("%d", pa); // scanf() will write to a through pa
...
}
Note also that when passing an array to a function (such as when using the "%s" conversion specifier to read a string), you don't need to use the & operator; the array expression will implicitly be converted to a pointer type:
int main(void)
{
char name[20];
...
scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
...
}
If you're asking a question like this, I would recommend just learning for now "it just does".
You will learn that you need an ampersand because scanf takes one or more pointer arguments. If a is an int variable, it is not a pointer. &a ("the address of a") is a pointer, so it will work with scanf.
This is because in C, functions parameters are passed by value. In order for the scanf() function to modify the 'a' variable in your main() function, the address of 'a' shall be given to scanf(), hence the usage of the ampersand (address of).
Because scanf requires a pointer to the variable (i.e. a reference) that the value will go into.
You don't always need to use an & with scanf. What you need to do is to pass pointers. If you're new to C, you should spend some time reading the comp.lang.c FAQ:
http://c-faq.com/
Specifically:
Why doesn't the call scanf("%d", i) work?
Why does the call scanf("%s", s) work?
The '&' in scanf is only required to get the address of a variable. You can use scanf without '&' by using pointers:
int myInt;
int * pointer_to_int;
pointer_to_int = &myInt;
scanf("%d", pointer_to_int);
In general, using '&' is often easier than creating pointer to avoid using the '&'.

Resources