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

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

Related

What does this number stand for

I was simply trying out this code which is saw in a tutorial
#include <stdio.h>
int main() {
int a = 34;
int *ptra = &a;
printf("%d\n", ptra);
return 0;
}
Here when I run this code I get a number as an output. The number was 6422216.
What does this number stand for ?
(I was trying to learn pointer arithmetics)
Your program prints out the memory address of where the integer a is stored and I'll explain why but firstly you need to know what the symbols stand for.
* - is used to declare a pointer and when placed before a address it will give you what is stored at that address
& - will give you the address of the variable written after it
So, first you assign the integer a value of 34
int a = 34;
Then you create a pointer of a integer called ptra and assign it the memory address of where the integer a is stored
int *ptra = &a;
And finally you print the value of ptra which is the memory address of where the integer a is stored
printf("%d\n", ptra);
If you would wan to print out the value of a through the integer, then you should replace ptra with *ptra in the printf function.
The behavior of the code sample is actually undefined because you pass a value of type int * where printf expects an int as the argument for conversion %d.
The code may be corrected as printf("%p\n", (void *)ptra); or possibly printf("%llu\n", (long long)ptra);
The value printed is the address of the variable a, which is system specific and may change from one run of the program to another, as is the case on OS/X that implements address space randomisation to increase the difficulty for hackers to exploit some program flaws.
To cut a long story short, the answer to your question What does this number stand for? is the number is the numeric value of the address of variable a which is stored in the pointer ptr. Since addresses can be wider than the int type, you should use a longer type such as long long, preferably unsigned:
printf("%llu\n", (long long)ptra);

Why does char* of an array point to the entire array instead of the address?

I've seen some similar questions asked on here, but haven't been able to find a concise answer.
In learning pointers, I've come to understand that
in a case of
int test=1; int* p = &test;
printing "p" with printf("%p", p); will give the address of test, while printing *p with printf("%d", *p); will give the actual value of test, which is what ptr p points to.
Now, for doing this with a char, doing
char word[] = "test"; char* ptr = &word[0];
then printing ptr with printf("%s", ptr); gives the output "test", but I expected it to give the address of word[0].
I have figured out that if I do printf("%p", ptr); it does print the address.
So my question is, does this pointer contain both the address and the value of the array test[]? Or does printf just grab what it needs based off of which of %s or %p you use, and in that case, why couldn't you just do printf("%d",test); in my earlier example and get the value of test rather than the address? Is the fact that I'm using %s automatically outputting the entire array since it starts at that address?
%s tells printf to take the pointer it is given and print the first character that is there, then the character after that, then the character after that, and so on until printf finds a null character (a character that has value zero).
So, this not about a pointer pointing to the “entire array.” The pointer just points to one thing. It is about the command given to printf. %p says “print the value of the pointer.” %s says “print the characters at the location pointed to.”
… why couldn't you just do printf("%d",test); in my earlier example and get the value of test rather than the address?
%d is a command to printf to print the value of the int it is passed. You should not pass it a pointer for this because printf is expecting an int. That is just what the command is for.

how to print the value of a pointer from a structure

The value contained in the pointer 'p' from the structure below is wrong printed and i can not find the way to print it right. What's the right code for it?
The code:
#include <stdio.h>
struct my_struct{ //structure definition
int a,*p;
};
int main(){
my_struct var;
var.a = 5; //variable definition
var.p = &(var.a); //pointer gets address from variable
printf("%d\n",var.p); // the number 2686744 is printed instead of the number '5'
return 0;
}
The %d format specifier to printf expects an int, but you're passing it an int *.
You need to dereference the pointer to obtain an int:
printf("%d\n",*(var.p));
You are printing the literal address of the pointer (i.e. not the value it points to, but the address in memory of where it points) when you write printf("%d\n", var.p). To access the value pointed to you need to dereference the pointer with printf("%d\n", *(var.p)).
As a side note: if you ever do want to access the address of a pointer for whatever reason in a printf family function, use the %p format specifier instead: http://www.cplusplus.com/reference/cstdio/printf/
You're not dereferencing the pointer
my_struct var;
var.a = 5;
var.p = &(var.a);
printf("%d\n",*(var.p)); //this will work
Use *var.p at print to dereference the pointer p and get it's value. Right now you are printing the memory location in decimal.
Your pointer var.p is simply containing an address. When i say containing, i mean it's value is an address.
In your case, this is the var.a's address.
When you try to print its value, you will print the var.a's address.
If you want to print what is CONTAINED at this address, or what is the VALUE at this address, you have to put a star before it.
In your case, you do not want to print var.p's value, as this an address, but you want to print the value contained at this address, using *(var.p).
Take care, there may be a difference in some languages between "var.p" and "(var.p)".
Imagine these operations in mathematics : (2x3)² and 2x3².
On the first operation, the ² will affect the whole multiplication, when, in the second operation, the ² will only affect the number 3.
In fact, you may want to try it by yourself to know how the language you are using work, *var.p may give you a way different result :)
However, using parenthesis in this case is a good practice, even if the language does give the same result.
PS : Just an extra information, if you ever need to print an address (which is not your case at the moment, you only want to print a decimal) using printf, replace %d by %p.

C - What does int *p; p=15; does?

What is the difference between these two code samples? When I print the variable p, it prints the assigned value like below.
int *p;
p = 51;
printf("%d",p);
Output: 51
When I try to assign p=15, am I making memory address "15" in the ram as a pointee to the pointer p? When I try to add int c = 5 +p; it gives output as 71. Why am I getting 71?
I thought that the memory address "15" could store any information of the OS, programs, etc. But it exactly stores int for precise. Though I change the value p = 150; it gives int . How is that possible? What's happening under the hood?! I really don't understand.
Your code is illegal. Formally, it is not C. C language prohibits assigning integral values to pointer types without an explicit cast (with the exception of constant 0)
You can do
p = (int *) 51;
(with implementation-defined effects), but you cannot do
p = 51;
If your compiler allows the latter variant, it is a compiler-specific extension that has nothing to do with standard C language.
Typically, such assignment makes p to point to address 51 in memory.
On top of that, it is illegal to print pointer values with %d format specifier in printf. Either use %p or cast pointer value to proper integer type before using integer-specific format specifiers.
So you're telling that pointer that it points to 0x15. Then, you tell printf to print it as a decimal integer, so it treats it as such.
This reason this works is that on a 32 bit system, a pointer is 4 bytes, which matches the size of an int.
p points to a place in memory. *p is the contents of that space. But you never use the contents, only the pointer.
That pointer can be viewed as just a number, so printf("%d",p) works. When you assign a number to it, it interprets that as an offset into memory (in bytes). However, the pointer is supposed to contain ints, and when you add a number to a pointer, the pointer advances by that many spaces. So p+5 means "point to the int 5 spaces past the one you're pointing at now", which for 4-byte ints means 20 bytes later, hence the 71.
Otherwise, you've said you have a pointer to an int, but you're actually just doing all your stuff to the pointer, not the int it's pointing to.
If you actually put anything into the place you were pointing, you'd run into all kinds of trouble. You need to allocate some unused memory for it (e.g. with malloc), and then read and write values to that memory using *p.

Wrong format specifier in scanf("%d", unsigned short int) after gets(pointer) changes the char pointer's value, but why?

I've recently tried some C-programming and stumbled upon the following problem. I'm using NetBeans 7.4 64 IDE with MinGW 32 Bit. This is a short example code which highlights my problem:
int main(void) {
unsigned short int temp;
char *pointer;
pointer = malloc(12 * sizeof(char));
printf("The pointers value is %d \n", (int)pointer);
printf("Type a short string:\n");
gets(pointer);
printf("The pointers value is %d \n", (int)pointer);
printf("Type an int: \n");
//This line changes the char pointer to an apparently random value
scanf("%d", &temp);
//Segmentation fault upon this point
printf("The pointers value is %d \n", (int)pointer);
//And here as well
free(pointer);
return (EXIT_SUCCESS);
}
Until scanf everything is fine. The string read by gets is written into the memory space pointer is pointing at. But AFTER scanf has been processed, pointer's value is changed so that pointer is pointing on any space. So not only my string's lost, but I also get segmentation faults when trying to access / free memory which doesn't belong to my program.
The value change is apparently random. Each time I'm debugging this program, the pointer's changed to another value.
I've already deduced that the unsigned short int is at fault, or rather the wrong format specifier (%d instead of %hu) in my scanf. If I either change unsigned short int to int or use %hu as specifier, everything works fine. So there's the solution.
But I'm still curious why and how the pointer's affected by this mistake. Can anyone help me there?
Your program has undefined behavior.
You need to tell scanf() that there's only room for a short integer, how else is it going to know which size to store the number as?
Change to:
scanf("%hu", &temp);
Where h means "half", i.e. short, and u is for unsigned. Your failure to use the proper format conversion specifier caused undefined behavior, in which scanf() overwrote a neighboring variable in memory.
Also, please note that gets() is deprecated due to being very dangerous: please don't use it. Use the much more well-behaved fgets() instead. And never scale an allocation by sizeof (char), that's just a very hard-to-read way of writing * 1 which adds no value.
Because in C nothing prevents you from writing beyond a particular variable's memory. Everything is just an address, knowing how many bytes after this address you can write to is up to you and not something the compiler is going to check.
a short int uses less bytes of memory than a regular int. You allocated a short int. Then you asked scanf to write a normal int. scanf wrote beyond the allocated memory, and overwrote part of char *pointer which happened to be located just after your short int. This is called undefined behavior because there is no knowing what you could be overwriting. The fact that pointer is located in memory right after temp is a coincidence.
pointer now points to an invalid memory address, and you get a segmentation fault when you try to access it.
A pointer is actually just another integer variable (a long) that stores a memory address.

Resources