%p vs %x in format String - c

Hi im a bit confused in String formats in C.
can someone explains me what is the output of every print of typed here?
printf("%p", pointer);
printf("%x", pointer);
printf("%x", &pointer);

%p means “print a pointer.” You should pass it a pointer that has been converted to void *. %x means “print an unsigned int in hexadecimal.” You should pass it an unsigned int; it is not correct to pass it a pointer.
Suppose we have:
char *pointer = "Hello";
char array[] = "World";
Then, in:
printf("%p", (void *) pointer);
printf("%p", (void *) array);
The value of pointer will be printed in some implementation-defined manner. (It should show you the address that is stored in pointer.)
In the second printf, the array array will be converted to a pointer to its first element, and the value of this pointer will be printed in the implementation-defined manner.
Note that I inserted casts to (void *). This is the proper way to use %p.
In:
printf("%x", (unsigned) pointer);
printf("%x", (unsigned) array);
The value of pointer will be converted to an unsigned int. The result of this conversion is implementation-defined. It should not be surprising, but it may be different from what you see with %p. Additionally, an unsigned int may be too narrow to contain the full value of the pointer, in which case some information will be lost.
After this conversion, the first statement will print the value in hexadecimal (without a leading “0x”, whereas using %p often does include a leading “0x”). The second statement will again convert array to a pointer to its first element, then convert that to unsigned int, and then print that in hexadecimal.
If unsigned int is wide enough, it is possible, even not unlikely, that the values printed by this method will show the same hexadecimal values as shown by the %p method, but you cannot rely on that.
Note that printing these using %x without the cast to unsigned has behavior not defined by the C standard—it is an error to pass a pointer for a %x specification. You must convert it first. Your original code, without the cast, could result in the value being printed coming from some arbitrary data not related to the pointer, or it could have caused your program to abort, or it could have printed the correct address, or it could have done something else—the behavior is not defined.
In:
printf("%x", (unsigned) &pointer);
printf("%x", (unsigned) &array);
The address of pointer, rather than its value, will be converted to an unsigned int and then printed in hexadecimal. This will almost certainly be different than the result of printing pointer.
For &array, the address of the array will be converted to unsigned. Unlike the previous statements, array is not converted to a pointer to its first element. This is because & is a special operator that suppresses this conversion. It returns the address of the array.
The address of the array is the “same” as the address of its first element, because, in memory, the array starts where its first element starts. However, the pointers may have different representations, and it is possible that converting &array to unsigned int may produce a different value than converting array to unsigned int. Nonetheless, in most C implementations, they produce the same value, so you will see the same result for printf("%x", (unsigned) &array); as you did for printf("%x", (unsigned) array);.

first is for pointers and the second one for integers even if the result very often will be the same. And this is explaining everything. If you want to print pointer %p if integer %x.
All other deliberations are wrong as using wrong format specifier invokes the UB.

Related

Dereference pointer *p vs ("%s", p)

I'm new to C and currently learning about Pointers. All I know is a pointer is basically a variable that contains the address of another variable and to get its data we need dereference pointer :
int i = 10;
int *pi = &i;
printf("%d",*pi);
But watching some tutorials on yt I also see
char *p = "Hello";
printf("%s",p); //print out Hello//
I also test it myself
int *i = 10;
printf("%d",i); //print out 10//
I have searched about it and know it's a kind of read-only memory instead of char []. But p and i here are pointers and how can they work with %s and %d directly but not dereferencing *i *p. Can anyone explain it to me pls.
A pointer doesn't necessarily contain address of another variable, it contains an address of some data, which can but doesn't need to be in a variable. For example, the pointer may point to dynamically allocated data, or to data that is part of an array, or to static data that ships with the executable.
In case of char *p = "hello", p points to the first character of a character array prepared by the compiler, and which contains the letters hello followed by a terminating zero character. The %s specifier is designed to receive such a pointer and print the letters up to the zero character, which is why it works.
Your second example, where you print a pointer using %d is quite different in nature. It abuses the fact that addresses have integer representations, and that T *x = <some integer> implicitly casts the integer to the corresponding memory address. In your case you create an invalid pointer pointing to the invalid address 10. Then you proceed to call printf with the %d specifier without dereferencing the pointer. Since %d expects an integer, and the address is also internally represented as an integer, this prints the invalid address 10 the pointer points to. However, pointers and integers don't have compatible memory representations, so this kind of code only works by accident, and exhibits undefined behavior.
To generalize the answers already given, a pointer is simply a variable that contains a memory address. How the code attempts to use that memory address depends on the context you give to it. A pointer can point to data, or even code, in the form of a function pointer. You could even assign any arbitrary value you want to a pointer, and the code will attempt to use it, though that likely will fail or give unpredictable results.
It's perfectly legal to do this:
int *i = (int *)0x12345678;
and dereferencing that pointer (int x = *i;) is also perfectly legal, but will almost certainly fail, because 0x12345678 is likely not an address that is valid when your code runs. Even if it is, the code generated by the C compiler will attempt to access those bytes in a manner that may not correspond to whatever is stored there. In the above case, if you're on, say, a 32-bit x86, the code will interpret the 4 bytes starting at 0x12345678 as a 32-bit signed integer in little-endian format. Whatever is actually there may not result in a usable value.
hi Have Following Have Example Of Pointer With Array
enter code here
#include<stdio.h>
#include<conio.h>
void main()
{
int x,*px,i,**pxx;
x=10;
px=&x; //Right Way To iniFor Pointer
pxx=&px+1; //store address of another pointer
clrscr();//we use px+1 because have 2 address 1 is x and 2 px
printf("\n\n passed value of x in pointer");
printf("\n\n the value of x:-%d",x);
printf("\n the value of px:-%d",*px);//Using * u access a value
printf("\n the value of pxx:-%d",**pxx);
printf("\n\n the address of pointer variable");
printf("\n\n the &x address:-%p",&x);
printf("\n the px &address:-%p",&px); //using %p Or %x Acces address
printf("\n The address of pxx:%p",&pxx);
for(i=0;i<5;i++)
{
px=px+1;
*px=i;
printf("\n%d %p",*px,px);
}
printf ("\n\nThe array of Pointer\n");
for(i=0;i<5;i++)
{
pxx=pxx+1;
printf("\n%d %p",*pxx,pxx);
}
getch();
}
in this example pointer used as a array
**pxx is have 2 address 1 is x 2 is pxx
that reason we used pxx=&px+1 to access address of px
*-represents value at certain variable.
&-represents address of certain variable.
*p=10 let's say the address of p might be "662543" so now by you have stored the value 10 in the address "662543".
and nor if you print
*p - output will be 10, and
&p- output will be 662543.
and talking about the % sign its a format specifier. like %d for integer, %f for float and %s for string etc.
and difference between %d and %i is as follows-
%d takes integer value as signed decimal integer i.e. it takes negative values along with positive values but values should be in decimal otherwise it will print garbage value.( Note: if input is in octal format like:012 then %d will ignore 0 and take input as 12) Consider a following example.
%i takes integer value as integer value with decimal, hexadecimal or octal type.
To enter a value in hexadecimal format – value should be provided by preceding “0x” and value in octal format – value should be provided by preceding “0”.

Memory address and content

I have written
int a;
printf("addr = %p and content = %x\n", (void*)(&a), *(&a));
printf("addr = %p and content = %x\n", (void*)(&a)+1, *(&a)+1);
What I see in the output is
addr = 0x7fffffffde3a and content = 55554810
addr = 0x7fffffffde3b and content = 5555
I expect to see one byte in each address. However, I don't see such thing. Why?
First of all, pointer arithmetic and the dereference operator honors the data type.
Remember, a pointer arithmetic, which generates a pointer one past the last element of an array is valid, but attempt to dereference the generated pointer is undefined behavior.
Attempt to dereference a pointer which points to invalid memory location is undefined behavior.
That said,
Quoting C11,
The unary * operator denotes indirection. [...] If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’.
So, in your case, *(&a) is the same as a, which is of type int, and the format specifier prints the integer value stored in a.
If you want to see the byte-by-byte value, you need to cast the pointer (address of a) to a char * and then, dereference the pointer to see value stored in each byte.
So, (void*)(&a)+1 should be changed to (char*)(&a)+1 to point to the next byte of memory.
If you want to print bytes, then play with bytes:
use unsigned char* or uint8_t* for pointers
use %hhx to tell printf that input value is character length.
Example:
int a = 0x12345678;
printf("addr = %p and content = %hhx\n", (void*)&a, *(uint8_t*)&a);
printf("addr = %p and content = %hhx\n", ((void*)&a)+1, *((uint8_t*)&a+1));
Result in my little-endian env:
addr = 0xbedbacac and content = 78
addr = 0xbedbacad and content = 56
And don't forget to use *((uint8_t*)&a+1) instead of *(uint8_t*)&a+1. In the example the later would return 79 (78+1).
You've used the formatting directive %x. %x expects an unsigned int. The type of what you pass as the corresponding argument to printf does not change that. printf will read an unsigned int values from its arguments, no matter what you pass to it. If what you pass something that isn't compatible with what printf reads, the behavior of your program is undefined.
You happen to pass an int. An int is not an unsigned int, but it's close enough that when you read an int expecting an unsigned int, the value remains the same if the integer is positive or zero. Negative integers are mapped to a large positive value (UINT_MAX - a on machines using two's complement representation, which is almost all machines).
If you pass a char (signed or not) to printf when it expects an int (signed or not), the behavior is well-defined due to another feature of the C language, which is promotions. Values of integer types that are smaller than int (i.e. char and short) are converted to int¹. So the following program snippet is well-defined and prints the value of a byte at the address p (assuming that … is replaced by a valid pointer value):
unsigned char p = …;
printf("addr = %p and content = %x\n", (void*)p, *p);
*(&a) is the same thing as a. To see just one byte of a, you could cast the pointer &a to the type unsigned char *.
printf("addr = %p and content = %x\n", (void*)&a, *(unsigned char *)(&a));
This will print one byte of the representation of a in memory. Note that the representation depends on the machine's endianness.
Your code snippet doesn't initialize a, so the first call to printf prints whatever garbage happens to be at the location of a in memory at this time. This assumes that int does not have any trap representation, which is the case on virtually all C implementations.
The second call to printf tries to print *(&a)+1. This is just a+1. The output you get is surprising: are you sure you didn't actually run the program with *(&a+1)? This seems to be what you wanted to explore. With *(&a+1), the behavior of your program would be undefined, because this looks one int past a, and a is not in an array of two or more ints. In practice, you'd be likely to get whatever was just below a on the stack, but that's not something you can count on.
If you wanted to see the byte value at an address which is 1 past the start of a in memory, you'd need to cast the pointer to a byte pointer first. When you add an integer n to a pointer, this doesn't add n to the address stored in the pointer, it adds n to the pointer itself. This is only useful when the pointer points to a value inside an array; then p + n points to n array elements past p. In fact, p[n] is equivalent to *(p+n). If you want to add 1 to the address, then you need to obtain a byte pointer, i.e. a pointer to unsigned char. Contrast:
int a[2] = {0x12345678, 0x9abcdef0};
printf("addr = %p and content = %x\n", (unsigned char*)(&a) + 1, *((unsigned char*)(&a) + 1));
printf("addr = %p and content = %x\n", (&a) + 1, *((&a) + 1));
This is well-defined (but with an implementation-defined value since it depends on the platform's endianness) provided that int consists of at least two bytes (which is not strictly mandatory in C, but is the case everywhere except in a few embedded systems).
(void*)(&a) + 1 is not standard C, because void doesn't have a size so it doesn't make sense to move a pointer to void one void element further. However some implementations such as GCC treat void* as byte pointers, just like unsigned char *, so adding an integer to a void* adds this integer to the address stored in the pointer.
¹ Or to unsigned int if the smaller type doesn't fit in a signed int, e.g. on a platform where short and int have the same size.

Why does sizeof(*"327") return 1 instead of 8 on a 64 bit system?

printf("%lu \n", sizeof(*"327"));
I always thought that size of a pointer was 8 bytes on a 64 bit system but this call keeps returning 1. Can someone provide an explanation?
Putting * before a string literal will dereference the literal (as string literal are array of characters and will decay to pointer to its first element in this context). The statement
printf("%zu \n", sizeof(*"327"));
is equivalent to
printf("%zu \n", sizeof("327"[0]));
"327"[0] will give the first element of the string literal "327", which is character '3'. Type of "327", after decay, is of char * and after dereferencing it will give a value of type char and ultimately sizeof(char) is 1.
The statement:
printf("%lu \n", sizeof(*"327"));
actually prints the size of a char, as using * dereferences the first character of string 327. Change it to:
char* str = "327";
printf("%zu \n", sizeof(str));
Note that we need to use %zu here, instead of %lu, because we are printing a size_t value.
The string literal is an anonymous, static array of chars, which decays to a pointer to its first character -- that is, a pointer value of type char *.
As a result expression like *"abc" is equivalent to *someArrayOfCharName, which in turn is equivalent to *&firstCharInArray which results in firstCharInArray. And sizeof(firstCharInArray) is sizeof(char) which is 1.
Good answer by haccks.
Also, the behaviour of your code is undefined, because you have used the wrong format specifier.
So, use %zu instead of %lu because sizeof() returns size_t and size_t is unsigned.
C11 Standard: §7.21.6.1: Paragraph 9:
If a conversion specification is invalid, the behavior is
undefined.225) If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

Type casting char pointer to integer pointer

So I saw a few example on how the endianness of an architecture could be found. Let's say we have an integer pointer that points to an int data type. And let's say the int value is 0x010A0B12. In a little endian architecture, the least significant byte, i.e, 12, will be stored in the lowest memory address, right? So the lowest byte in a 4-byte integer will be 12.
Now, on to the check. If we declare a char pointer p, and type cast the integer pointer to a char * and store it in p, and print the dereferenced value of p, we will get a clue on the endianness of the architecture. If it's 12, we're little endian; 01 signifies big endian. This sounds really neat...
int a = 0x010A0B12;
int *i = &a;
char *p = (char*)i;
printf("%d",*p); // prints the decimal equivalent of 12h!
Couple of questions here, really. Since pointers are strongly typed, shouldn't a character pointer strictly point to a char data type? And what's up with printing with %d? Shouldn't we rather print with %c, for character?
Since pointers are strongly typed, shouldn't a character pointer strictly point to a char data type?
C has a rule that any pointer can be safely converted to char* and to void*. Converting an int* to char*, therefore, is allowed, and it is also portable. The pointer would be pointing to the initial byte of your int's internal representation.
Shouldn't we rather print with %c, for character?
Another thing is in play here: variable-length argument list of printf. When you pass a char to an untyped parameter of printf, the default conversion applies: char gets converted to int. That is why %d format takes the number just fine, and prints it out as you expect.
You could use %c too. The code that processes %c specifier reads the argument as an int, and then converts it to a char. 0x12 is a special character, though, so you would not see a uniform printout for it.
Since pointers are strongly typed, shouldn't a character pointer strictly point to a char data type?
This is kind of undefined behavior - but such that most sane implementations will do what you mean. So most people would say ok to it.
And what's up with printing with %d?
Format %d expects argument of type int, and the actual arg of type char is promoted to int by usual C rules. So this is ok again. You probably don't want to use %c since the content of byte pointed by p may be any byte, not always a valid text character.

What Actually this line of code `ptr=(char *)&a;` does?

I have the code :
#include<stdio.h>
void main(){
int i;
float a=5.2;
char *ptr;
ptr=(char *)&a;
for(i=0;i<=3;i++)
printf("%d ",*ptr++);
}
I got the output as 102 102 -90 64. I couldn't predict how it came, I get confused with this line ptr=(char *)&a;. Can anyone explain me what it does? And as like other variables the code *ptr++ increments? Or there is any other rule for pointers with this case.
I'm a novice in C, so explain the answer in simple terms. Thanks in advance.
This is called a cast. In C, a cast lets you convert or reinterpret a value from one type to another. When you take the address of the float, you get a float*; casting that to a char* gives you a pointer referring to the same location in memory, but pretending that what lives there is char data rather than float data.
sizeof(float) is 4, so printing four bytes starting from that location gives you the bytes that make up the float, according to IEEE-754 single-precision format. Some of the bytes have their high bits set, so when interpreted as signed char and then converted to int for display, they appear as negative values on account of their two's-complement representation.
The expression *ptr++ is equivalent to *(ptr++), which first increments ptr then dereferences its previous value; you can think of it as simultaneously dereferencing and advancing ptr.
That line casts the address of a, denoted &a, to a char*, i.e. a pointer to characters/bytes. The printf loop then prints the values of the four constituent bytes of a in decimal.
(Btw., it would have been neater if the loop had been
for (i=0; i<sizeof(a); i++)
printf("%d ", ptr[i]);
)
The line ptr=(char *)&a; casts the address of the float variable to a pointer of type char. Thus you are now interpreting the 4 bytes of which the float consists of as single bytes, which values you print with your for loop.
The statement *ptr++ post-increments the pointer after reading its value, which means, you read the value pointed to (the single bytes of the float) and then advance the pointer by the offset of one byte.
&a gets the address of a, that is, it yields a pointer of type float *. This pointer of type float * is then cast to a pointer of type char *.
Because sizeof(char) == 1, a can now be seen through ptr as a sequence of bytes.
This is useful when you want to abstract away the type of a variable and treat it as a finite sequence of bytes, especially applicable in serialisation and hashing.

Resources