Using scanf %p UB - c

From the C11 Standard (draft): 7.21.6.2/12:
If the input item is a value converted earlier during the same program
execution, the pointer that results shall compare equal to that value;
otherwise the behavior of the %p conversion is undefined.
Can someone provide a code for this part of standard please. Can not understand the use of getting %p from input too.

First, here is a small demo that uses string versions of input and output (demo):
int val = 123;
char buf[100];
sprintf(buf, "%p", (void*)&val);
printf("Original =%s\n", buf);
void *ptr;
sscanf(buf, "%p", &ptr);
printf("Read back=%p\n", ptr);
int *iPtr = ptr;
if (iPtr == &val) {
printf("Pointers match\n");
}
The sprintf at the top writes the pointer to the output buffer; sscanf reads it back.
The string fed into sscanf matches exactly the string that was produced by sprintf, so the standard guarantees that iPtr == &val is going to evaluate to true, and the behavior is defined. Passing a string that does not match anything that has been produced by the same running program would be undefined behavior.

int main(){
int c =5;
int *p;
printf("Address of C: %p\n Please Enter the above address: " , &c);
scanf("%p", &p);
*p=10;
printf("\nNew value of C: %d", c);
}
You could manually set pointers via scanf. Dangerous if you have a typo however.

Related

How do I change contents of a variable using a pointer?

I'm working with pointers for the first time in C. I tried to declare, initialize, and assign a memory address to 3 pointers, then print the addresses and values of each pointer and variable, then assign a value to the pointer so that the value of the data which has the memory address is changed. Here is the code:
int i = 5;
float f = 7.77;
char c = 'a';
int iNumber = 2;
float fNumber = 5.55;
char cCharacter = 'c';
int *iPtr;
float *fPtr;
char *cPtr;
iPtr = &i;
fPtr = &f;
cPtr = &c;
printf("\nThe current values are: ");
printf("%d %f %c", i, f, c);
printf("\nThe addresses of each pointer are: ");
printf("%d %f %c", iPtr, fPtr, cPtr);
iNumber = *iPtr;
fNumber = *fPtr;
cCharacter = *cPtr;
printf("\nThe modified values are: ");
printf("%d %f %c", i, f, c);
printf("\nThe addresses of each pointer are: ");
printf("%d %f %c", iPtr, fPtr, cPtr);
return 0;
is when I change the values of i, f, and c.
However, when I run the program the memory addresses for the int variables are not in hexadecimal format, they're in random numbers that change every time I run the program. The addresses for the char ones don't appear. Also, when I modifiy the values in the pointers the variables they're pointing to don't change. I thought this was how you referenced by value, i'm really confused.
This (second) call of printf
printf("\nThe addresses of each pointer are: ");
printf("%d %f %c", iPtr, fPtr, cPtr);
is wrong. You are trying to output pointers as objects of the type int, float and char that does not make sense.
If you want to output stored addresses in the pointers you need to write
printf("\nThe addresses of each pointer are: ");
printf("%p %p %p\n", ( void * )iPtr, ( void * )fPtr, ( void * )cPtr);
(do not forgot to place the new line character '\n' in the format string)
Also in this call of printf
printf("\nThe modified values are: ");
printf("%d %f %c", i, f, c);
you are not outputting modified values. The values of the variables i, f, and c were not changed. It seems you mean instead
*iPtr = iNumber;
*fPtr = fNumber;
*cPtr cCharacter;
printf("\nThe modified values are: ");
printf("%d %f %c\n", i, f, c);
Changing the value using Pointer
I think ultimately you want to change the value of i from 5 to the value of the variable iNumber, which is 2 using pointer.
Your code :
iNumber = *iPtr;
fNumber = *fPtr;
cCharacter = *cPtr;
What you've done here is, assigned the value of each pointer variable to the iNumber, fNumber, cCharacter variables.
So now if you print those variables you could see that the values of iNumber, fNumber, cCharacter is changed to 5, 7.77, a accordingly. Because, those pointer variables are pointing to the address of the first 3 variables, that are &i, &f and &c as you've might guessed.
Solution :
*iPtr = iNumber;
*fPtr = fNumber;
*cPtr = cCharacter;
As you can see in the above snippet, you need to assign the new values/variable to the pointer variable instead of doing the opposite.
Printing the Address of a Variable
Your code :
printf("\nThe addresses of each pointer are: ");
printf("%d %f %c", iPtr, fPtr, cPtr);
To print the memory addresses of variables in C, you need to use the %p format specifier in printf() instead of %d or %f. The %p format specifier is specifically used for printing memory addresses in hexadecimal format.
Also, when you're printing the memory address of a variable, you have to use the address-of operator (&), which is used to get the address of a variable.
Solution :
printf("\nThe addresses of each pointer are: ");
printf("%p %p %p", &iPtr, &fPtr, &cPtr); // hexadecimal
// not the standard way to represent memory addresses
printf("%u %u %u", &iPtr, &fPtr, &cPtr); // decimal
Tip : You can print the address in Decimal instead of Hexadecimal
for ease of mind, just by replacing %p to %u. (the adreess-of operator remains intact while printing memory addresses)
Why do the memory addresses change on each run?
When you run your C program, the computer assigns a memory address to each variable in your program. The memory address is typically represented as a large number, usually in hexadecimal format. The memory address is important because it allows the program to access and manipulate the value of the variable stored at that location in memory.
However, the memory address of a variable can change from one program run to another, for a number of reasons, such as randomization of the memory space, allocation of memory on the heap or stack, or optimization of the program code by the compiler or linker.
But as a beginner, you don't have to worry about it.

scanf statement in c and pointers

I read many previous questions but none of them cleared my doubt.
When I define and initialize a pointer as
int a = 10;
int* p;
p = &a;
printf("%d", *p); // this will print the value of 'a' towards which p is pointing
But when I use scanf statement like-
int *p;
scanf("%d", &p);
printf("%d", p); // is this form of input similar to the one above?
Also when I use char pointer to read a string-
char* name[10];
scanf("%s", name);
printf("%s", name); // runs correctly.
What I know is that scanf expects pointer as input (like &a if it's like int a;)
But If I use--
char* names[5][10];
scanf("%s", names[1]); // reading the first name. Is this correct? because length of name can vary.
Now I am unable to print this, I tried no of ways.
A detailed explanation would be appreciated, my teacher isn't that good.
DOUBTS
When do we use * with a pointer? i.e. to print its value or for what?
Unable to scan char* xyz[a][b];
A brief explanation of my mistakes and the code above.
Edits-
int* arr[n];
for(int i =0; i<n; i++){
printf("Enter the salary of %d person:", i+1);
scanf("%d", &(arr[i]));
printf("\n");
}
Also, this type of assignment of value is not right?
printf("%d", p); // is this form of input similar to the one above?
no, %d expects an int argument, you're passing an int *. Supplying mismatched argument type for a conversion specifier invokes undefined behaviour.
That said, in case of
char* name[10]; // array of character pointers!
scanf("%s", name);
printf("%s", name); // runs correctly.
you're going wrong. Check the data types. %s expects the argument to be a pointer to a char array, so your code should be
char name[10]; // array of characters
scanf("%9s", name); // mandatory error check for success to be done.
printf("%s", name);
as, in most of the cases including this one, an array type decays to the pointer to the first element of the array, so while passing as function argument, name is actually of type char *.
Same goes with
char* names[5][10];
scanf("%s", names[1]);
changing that to
char names[5][10];
will suffice.

Why value of pointer changes after cast?

Code:
int main(void) {
register int rsp asm("rsp");
int temp=rsp;
printf("\n (rsp)%p \n", rsp);
printf("\n (temp)%p \n", temp);
printf("\n (void*)(rsp)%p \n", (void*)rsp );
printf("\n (void*)(temp)%p \n", (void*)temp );
return 0;
}
Output:
(rsp)0xffffcbe0
(temp)0xffffcbe0
(void*)(rsp)0xffffffffffffcbe0
(void*)(temp)0xffffffffffffcbe0
I suspect this is a silly question, but why does value of pointer changes after cast? I've tried to cast to different types and i always get same offset.
Thank you.
but why does value of pointer changes after cast?
int and rsp are int, not pointers.
Using "%p" is undefined behavior with int.
printf("\n (rsp)%p \n", rsp); // UB
printf("\n (temp)%p \n", temp); // UB
Yet let us assume the value, converted to unsigned was as printed by OP.
printf("\n (rsp)0x%x \n", (unsigned) rsp); // (rsp)0xffffcbe0
printf("\n (temp)0x%x \n", (unsigned) temp); // (temp)0xffffcbe0
When code coverts a pointer to int as in register int rsp asm("rsp");, it can lose significance #David Wohlferd. When converting an int to a pointer, various conversion mechanisms occur like sign extension to cope with the narrow int. The "%p" have an implementation specific format.
To be clear: OP's code does not certainly print the address of the original asm("rsp"). (Compiler specific extension).
C provides optional integer types (u)intptr_t that provide a conversion from/to an equivalent integer and object pointer. To save an object pointer in an integer, use those types. Unfortunately, C lacks a latching print specifier for printing the value of a non-void* pointer and (u)intptr_t, thus casting in the following.
#include <stdint.h>
#include <stdio.h>
char *s = "rsp";
printf("pointer %p\n", (void *) s);
uintptr_t i_ptr = (uintptr_t) s;
printf("integer 0x%jX\n", (uintmax_t) i_ptr);

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).

Need help understanding char and int pointers

In this code to print the value of int and char pointer variables, why do I access them differently? For the char pointer I write sampleclient but for the int I write *intid. Why does one use * but not the other?
int main()
{
char client[] = "ABCD";
int intid = 10;
samplepass(&client, &intid);
return 0;
}
void samplepass(char *sampleclient, int *intid)
{
printf("%s %d\n", sampleclient, *intid);
}
This is because %s format specifier expects a char pointer, while %d expects an integer argument. If you want to see the value of the pointers themselves(i.e. the address they point to) use %p.
In C, you can't pass a string (character array) to a function like printf, so you do the next best thing: pass it its address in memory. The function can then treat the memory address like an array using pointer arithmetic. So the way printf reads strings is by taking in a pointer to the string. Then %s displays the dereferenced string (ABCD here), not the pointer address (which you could get by using %p instead of %s).
The integer problem is more straightforward: the * in *intid means 'get the value stored at this address'. That's why it prints out 10, not the memory address.
The 'correct' format specifier to get a memory address is %p. But you could write:
int main()
{
char client[] = "ABCD";
int intid = 10;
samplepass(&client, &intid);
return 0;
}
void samplepass(char *sampleclient, int *intid)
{
printf("%d %d\n", sampleclient, intid);
}
On my machine, the output was
-2140958000 -2140958004
(and those are the addresses in memory of client and intid). Substituting %p for %d gives nicely formatted pointers with a 0x in front and conforms to the standard, so I'd use that.
For an output that looks like:
ABCD 10
change your line
from samplepass(&client,&intid);
to samplepass(client,&intid);

Resources