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.
Related
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”.
I am new to C and have some questions about the pointer.
Question 1 What`s differences b/w the following two? Which way is better to initialize a pointer and why?
int *p=NULL;
int *p;
#include <stdio.h>
void main()
{
char *s = "hello";
printf("%p\t%p",s);
//printf("%p\t%p",&s) it will give me unpredictable result every time
//printf("%p\t%p",(void *)&s) it will be fine
//Question3: why?
}
Question 2: I try to google what is %p doing. According to my reading, it is supposed to print the pointer. It that mean it print the address of the pointer?
Question 1, these are definitions of pointer p. One initializes the pointer to NULL, another leaves it uninitialized (if it is local variable in a function, and not global variable, global variables get initialized to 0 by default). Initializing with NULL can be good, or it can be bad, because compiler can warn you about use of uninitialized variables and help you find bugs. On the other hand compiler can't detect every possible use of uninitialized variable, so initializing to NULL is pretty much guaranteed to produce segmentation fault if used, which you can then catch and debug with a debugger very easily. Personally I'd go with always initializing when variable defined, with the correct value if possible (if initialization is too complex for single statement, add a helper function to get the value).
Question 2, %p prints the address value passed to printf. So printf("%p", pointer); gets passed value of variable pointer and it prints that, while printf("%p", &pointer); (note the extra & there) gets passed address of the variable pointer, and it prints that. Exact numeric format of %p is implementation defined, it might be printed just as a plain number.
Question 3 is about undefined behavior, because format string has more items than what you actually pass to printf. Short answer is, behavior is undefined, there is no "why". Longer answer is, run the application with machine code debugger and trace the execution in disassembly view to see what actually happens, to see why. Note that results may be different on different runs, and behavior may be different under debugger and running normally, because memory may have different byte values in different runs for various reasons.
1) The first is an initialization (to NULL in this case) the second is only a declaration of p as a pointer to int, no initial value is assigned to p in this case. You should always prefer an initialization to prevent undefined behavior.
2) You should cast to void* when using %p to print out a pointer (beware that you are using it too many times in your format specifier). The memory address to which p points is printed.
1)
int *p = NULL
defines and initializes a pointer 'p' to NULL. This is the correct way to initialize pointers in order to get "Seg Fault" if you forget to assign a valid address to this pointer later.
int *p
Only defines a pointer "p" with an unknown address. If you forget to assign a valid value to this pointer before using it, then some compilers will notify you about this mistakes while some others will not and you may access a non-valid address and get a run time error or undefined behaviour of the program.
2) "%p" is printing the address where the pointer is points. Since the pointer holds an address, then "%p" prints this address.
printf("%p\t%p",s);
So the first "%p" will print the address where the pointer "s" points which is the address which stores the string "hello". However, note that you are using twice "%p" but you providing only one pointer to print its address !!
Most compilers will not scream about this cause it is effect-less; however try to avoid it.
Answer1 :
int *p=NULL;
p is a pointer to a int variable initialized with NULL. Here NULL means pointer p is not pointing to any valid memory location.
int *p;
p is a pointer to a int variable. p in uninitialized. Reading uninitialized variables is Undefined Behavior. (one possibility if try to use is that it will throw a segmentation fault)
Answer2:
It prints content of pointer. I mean base address of string "hello"
The main difference is that in *p = NULL, NULL is a pre-defined and standard 'place' where the pointer points.
Reading from Wikipedia,
The macro NULL is defined as an implementation-defined null pointer constant,
which in C99 can be portably expressed as the integer value 0
converted implicitly or explicitly to the type void*.
This means that the 'memory cell' called p contains the MACRO value of NULL.
If you just write int *p, you are naming the memory cell with the name p but this cell is empty.
I was playing around with pointers the other day and came up with the following code where I explicitly cast an int variable to int * and print out the address of the explicitly casted variable
#include <stdio.h>
int main (void)
{
int d;
int *p1, *p2;
printf("%p\n", p1 = &d);
printf("%p\n", p2 = (int *) d);
return 0;
}
Here's the output:
ffbff71c
ffbff878
My question is what is that second address and what is contained there?
Garbage - you're printing out the value of an uninitialized variable. It's just total coincidence that it looks like your other address; initialize d to get a meaningful answer.
In the second print, you are not printing an address, but a value converted to an address!
In the first assignment, you're taking the address of the variable, which is just some RAM address. In the second assignment, you're converting the variable's value to a pointer. Since the variable is not initialized, that's the garbage value located at that RAM address.
It is just a random address in memory since d is not initialized.
As others have pointed out, you are converting an indeterminate value to a pointer. Performing that conversion, or indeed doing anything with that value other than overwriting it, produces undefined behavior.
If d's value were set prior to the conversion, then it would matter that C explicitly permits integers to be converted to pointers. However, for this case and most others, the standard says:
the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
[C2011, 6.3.2.3/5]
So basically, don't do that unless you know enough to determine reliably for yourself what the result will be with your particular combination of code, C implementation, compile and link options, and platform.
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.
Even after years of C, pointers still confuse me.
Are these two the same:
int *num;
someFunc(num)
and
int num;
someFunc(&num);
Declaring a variable with * makes it a pointer, & turns a variable (momentarily) into a pointer?
No they are not the same. In the first case you have a pointer which is pointing to some random memory location (as you have not initialized it). In the second case, the pointer obtained in someFunc will be pointing to a valid location (the address of variable num).
They are the same in terms of the function call. However
The difference is....
int num is an actual integer, which you take the address of. Which can then be placed into a pointer
int *num is a pointer to an int, however, with your code as is, it does not point to an actual int that can hold a value.
so only the second example is working code.
first one would be working if...
int x;
int *num = &x;
someFunc(num)
someFunc would look like
void someFunc(int *blah)
{
}
so basically int* num = &x is whats going on when you do the function call someFunc(&num) ie, its effectively just doing int* blah = &num
The second passes the address of the integer num, a perfectly reasonable thing to do. The first passes whatever happens to be stored in the pointer num. That should be the address of an int, but in your example num is uninitialized and the address probably points to garbage (at best).
& doesn't "turn a variable into a pointer", its an operator that returns the address of the variable. Which is, by definition, a pointer. Hence, no difference, the function someFunc receives a pointer value either way (in the first case it receives a copy the value of the pointer variable, in the second case it receives a copy of the return value of the operator &).
In the first case, you're declaring num to be a pointer to an integer. In the second case num is an integer.
To the someFunc function, in both cases the argument passed is a pointer to integer. So, to print the value you'll need to dereference printf("%d\n", *num).
In both cases the value would be some garbage since you haven't initialized.
Hope that helps.
Update On FreeBSD I got segmentation fault with the first one since the pointer which is not initialized may have pointed to somewhere that it is not supposed to.