In the example below, I pass a char into a function as a pointer. When the function prints out the memory address of the char, it is a different address. Am I dealing with two different variables in this case? Isn't that the same result as if I didn't use a pointer in the function argument (same as pass by value)?
char a = 'a';
printf("a=%p\n", &a);
showString(a);
//function
void showString(char *c){
c='b';
printf("c=%p\n", &c);
}
c is assigned the value 'b'. But if I check a after the function call, it still has the value 'a'. How does the above need to change so the value assigned in the function carries over outside of the function?
You are not using the pointer correctly: rather than assigning a new value to the object the pointer points to, you assign the pointer itself.
The call should use the address-of operator, and the assignment should be with the dereference operator:
showString(&a);
printf("a=%p\n", (void*)&a);
...
void showString(char *c){
*c='b';
printf("c=%p\n", (void*)c);
}
Now both printouts will produce the same address, and the value of char a in the calling function should change.
Note 1: The reason the compiler allowed c = 'b' assignment is somewhat odd: 'b' is considered a character constant, char is considered an integral type, and C lets you assign integers to pointers with the assumption that you know what you are doing better than the compiler.
Note 2: When you print a pointer with %p, and the pointer type is neither void* nor char*, a cast to void* is required. You are printing char*, so it can go without a cast, but I added the cast anyway, in case you want to try this out with pointers of a different type.
Your function should look like
//function
void showString(char *c) {
*c = 'b';
printf("c=%p\n", &c); //<---to print the address of C
printf("c=%c\n", *c); //<---to print the value that C is pointing
}
and when you call it you should pass the Address of a
char a = 'a';
printf("a=%p\n", &a);
showString(&a); //<---&a and not a
Related
I have a basic doubt, when we de-reference a pointer to an array why we get name of the array instead the value of first member of an array, I see this has been asked here but I didn't get it
exactly how?
dereferencing pointer to integer array
main()
{
int var[10] = {1,2,3,4,5,6,7,8,9,10};
int (*ptr) [10] = &var;
printf("value = %u %u\n",*ptr,ptr); //both print 2359104. Shouldn't *ptr print 1?
}
So, is it like when we dereference a pointer, it cancel out the reference operator and what we get is variable name, and in case of pointer to an array, it is the array name ?
main()
{
int a = 10;
int *p = &a;
printf("%d\n", *p) /* p = &a; *p = *(&a); and having a dereference cancel out the &, gives us *p = a ? */
}
Because ptr has type int (*)[10] which is a pointer to an array, *ptr has type int[10] which is an array type.
This array decays to a pointer to its first element when it is passed to printf which then prints the pointer value. The result would be the same if you passed var to printf instead of *ptr.
You do not get a variable name when you dereference a pointer. If the pointer points to an object the you get that object. If it does not point to an object then you get undefined behavior. In particular, if the pointer points to a whole array, then you get that array. That's a fundamental aspect of how pointers work.
However, a fundamental aspect of how arrays work is that in most contexts, an expression of array type is automatically converted to a pointer to the first array element. This address corresponds to the address of the array itself, but has different type (int * in your case, as opposed to int (*)[10]). Typically, converting these to an integer type produces the same value. Thus, in your example code, *ptr is equivalent to var, and each is automatically converted to a pointer of type int *, equivalent to &var[0].
But note also that it is not safe to convert pointers to integers by associating them with printf directives, such as %u, that expect a corresponding integer argument. The behavior is undefined, and in practice, surprising or confusing results can sometimes be observed. One prints a pointer value with printf by using a %p directive, and converting the pointer value to type void *. Example:
printf("pointer = %p %p\n", (void *)*ptr, (void *)ptr);
Combined with the type and value of ptr from your example, this can be expected to reliably print two copies of the same hexadecimal number.
When we declare a pointer to any integer say we declare it like
int i=5;
int *p=&i;
We use *p to get the value 5 and if we want the address we use p without asterisk sign to get the address. But in case of character array, when we say
char *str="HELLO";
We simply use str to get "HELLO" as output in printf function. Like this,
printf("%s",str);
Here we used str without asterisk.
Why aren't we getting an address and instead getting "HELLO" as output here while we get address in case of pointers to integers when we use the pointer variable without asterisk?
Okay first of all int *p=5; is wrong! you cant do that in the declaration of a pointer. at That time the pointer expects an adress. You should do int *p; and then *p = 5; to assign the value to it.
printf("%s",str); // prints the value of the variable, because its a pointer.
printf("%s",*str); // the * will cause to a segmentation fault
int *p // the * there is just used to tell the compiler that you are declaring a pointer of type integer.
/* another scope after declaring your pointer */
*p //is used to get value of a pointer variable.(dereference it)
&p //is used to get the adress of a pointer variable.
p //contains an adress.
Following is my code:
#include <stdio.h>
int main()
{
char a[10]="Hi!";
void f(char b[])
{
// 1. printf("*a is:%s\n",*a);
printf("&a is:%p\n",&a);
// 2. printf("&&a is:%p\n",&(&a));
printf("a's address is:%p\n",a);
printf("a's value is:%s\n",a);
printf("b's address is:%p\n",b);
printf("b's value is:%s\n",b);
// 3. printf("*b is:%s\n",*b);
printf("&b is:%s\n",&b);
}
f(a);
return 1;
getch();
}
Running the above code gives the output:
&a is:0028FF1C
a's address is:0028FF1C
a's value is:Hi!
b's address is:0028FF1C
b's value is:Hi!
&b is:∟ (
In the Output:
Why are there different outputs for &a and &b;
Although a and b have same reference.
Further,
I've mentioned 3 comments by their number.
If I remove slashes one by one and execute them,I get following 2 issues:
On executing comment no. 1 & 3:
"abc.exe has stopped working."
On executing comment no. 2:
abc.c: In function 'f':
abc.c:14:32: error: lvalue required as unary '&' operand
printf("&&a is:%p\n",&(&a));
^
Point 1: Nested functions are not standard C. They are supported as GCC extension..
Point 2: printf("&b is:%s\n",&b); is wrong and invokes UB, because of improper format specifier. You need to change that to
printf("&b is:%p\n",(void *)&b);
Point 3: &(&a) is wrong. the operand for & needs to be an lvalue, not another address, which is not an lvalue.
Related: C11, chapter §6.5.3.2, for the operand type
The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
and the return type
....result is not an lvalue.
You copy pasted the printf() and didn't change the specifier
printf("&b is:%s\n", &b)
/* ^ should be `p' */
The first comment, when executed is causing a problem because you are using the "%s" specifier and passing the first character of a which will be interpreted as an address, try this
printf("*a is: %c\n", *a);
The third comment presents the same problem.
The second comment, you need an intermidiate pointer to do that, like
char *c = &a;
char **d = &c;
printf("%p\n", (void *) d);
although it will print the same as printf("%p\n", (void *) a); because they all have the same address, the differenece is that the pointer arithmetic will work different.
Well, you shouldn't define functions inside another function - though some compilers accept that (like gcc), it isn't portable.
printf("&b is:%s\n",&b);
Here &b is the address of b, which is the address of the char array. In effect &b is the address of the parameter.
1.) and 3.) fail because you need to pass a pointer to a string. *a, is a dereferenced pointer, so, in effect, it's the first character of the string
2.) &&a is a pointer to a pointer to a pointer to a pointer (as a is already a pointer.
Note: This is the question author's own answer, see revision 3
I understood the above issues and here's the improved code:
#include<stdio.h>
#include<string.h>
int i;
char a[11]="F*** Yeahh!"; //String : char *
//'a' gets memory in "globals" area;'a' is a pointer to 'F'
void func();//Function Definition
int main()
{
func(a); //Passing reference of 'a' to func
getch();
return 1;
}
void func(char b[])
//'b' is given memory in 'stack' region;'b' has a reference
// to 'a' which in turn refer to 'F'
{
printf("*a is:%c\n",*a);
printf("&a is:%p\n",&a);
//printf("&&a is:%p\n",&(&a));//&()...Inside braces,there must be a
// value..
printf("a's address is:%p\n",a);
printf("a's value is:%s\n",a);
printf("b's address is:%p\n",b);
printf("b's value is:%s\n",b);
printf("*b is:%c\n",*b);
printf("&b is:%p\n",&b);
for(i=0;i<strlen(a);i++)
printf("String as an array of characters is:%c\n",b[i]);
}
Here's The Output:
*a is:F
&a is:00409000
a's address is:00409000
a's value is:F*** Yeahh!
b's address is:00409000
b's value is:F*** Yeahh!
*b is:F
&b is:0028FF20
String as an array of characters is:F
String as an array of characters is:*
String as an array of characters is:*
String as an array of characters is:*
String as an array of characters is:
String as an array of characters is:Y
String as an array of characters is:e
String as an array of characters is:a
String as an array of characters is:h
String as an array of characters is:h
String as an array of characters is:!
How do you deference a pointer to an array to get the value stored in it? For example:
void testFunction(int **test){
printf("%d", *test[1]);
}
int main()
{ int test[10];
test[1] = 5;
testFunction(&test);
return 0;
}
I get an error. Anyone could explain?
How do you deference a pointer to an array to get the value stored in it?
You use the * operator, as for every pointer. (Oh, and pay attention to operator precedence!)
void foo(int (*arr)[5])
{
printf("%d\n", (*arr)[0]);
}
int main()
{
int arr[5] = { 0, 1, 2, 3, 4 };
foo(&arr);
return 0;
}
Your code would have generated a diagnostic about an incompatible type being passed to the function. For example, GCC complains:
prog.c: In function 'main':
prog.c:9: warning: passing argument 1 of 'testFunction' from incompatible pointer type
You should pay attention to all diagnostics issued by your compiler, and make sure you understand them, and take the appropriate measures to address them. For this particular one, if you intend to pass in a pointer to an array, you need to write your function to accept such a thing. Then, when you dereference the pointer, you have an array. So, you access it like one.
void testFunction(int (*test)[10]){
printf("%d", (*test)[1]);
}
The [] has higher precedence that *, so the parentheses are required both for the function parameter argument, and for accessing the value in the printf(). When the pointer to int[10] is derferenced, the resulting value is the address of the first element of the array test defined in main. The [] operation then access the 2nd element of the array, and you get the value you expected.
You may be more convinced that your use of int **test is wrong for a pointer to an array if you note that the assertion below will always be true:
int test[10];
assert(&test == (void *)test);
As the compiler warning indicates, a pointer to a pointer to int is not the same as a pointer to an int[10]. The type being pointed to determines the type that results from a dereference.
So:
int test[10] = { [1] = 5 };
testFunction(&test);
This passes the address of test to testFunction. The address of a variable corresponds to its location in memory. This is not so different for an array, but the location in memory for an array variable is the address of its first element. So, the address returned by &test above is the same address returned by test alone.
This gives a disastrous consequence when you treat this pointer value as a pointer to a pointer to int in your testFunction. First, note that you ignore proper operator precedence, so the first dereference is:
test[1]
Since you declare the test parameter to be a pointer to a pointer to int, this increments the address in test by sizeof(int *) and treats the result as an int *. Then, you dereference again:
*test[1]
This now takes the value of test[1] and dereferences it again in an attempt to get an int. However, the address returned by test[1] has no relationship with the array test defined in main, and you are accessing a totally nonsensical memory location.
Even if you paid attention to the precedence with your pointer to pointer to int parameter type, a similar problem would have resulted.
(*test)[1]
Now, the pointer to int[10] is treated as a pointer to pointer to int is derferenced first. This results in the first sizeof(int **) bytes of the test array in main to be treated as a pointer to int. This is already a nonsensical value at this point, but the array dereference now increments this value by sizeof(int) bytes and dereferences that value in an attempt to obtain an int.
The other user gave an example of how it is usually done already, but if you insist on passing an int ** then because of operator precedence the syntax would be like:
void testFunction(int **test){
printf("%d", (*test)[1]);
}
int main()
{ int test[10];
test[1] = 5;
int *testptr= &test[0]; // or int *testptr= test;
testFunction(&testptr); // this passes an int **
return 0;
}
But in c the name of an array is a pointer to the array elements, so int *ptrtest and ptrtest[1] is more commonly used.
#include<stdio.h>
void main()
{
int *c=12345;
printf("dec:%d hex:%x", c ,&c); // (1)
}
The line (1) prints
dec:12345 hex:8af123
where 8af123 is obviously the address which is random and machine dependent.
When I put in
printf("dec:%d", *c); // (1)
it fails, obviously.
So my question is as per theoretical concept:
*c should holds the value 12345 but it is not. why?
And in this code:
#include<stdio.h>
void main()
{
char *c='a';
printf("address store in c:%d value point by c:%c address of c:%x", c,*c ,&c); //Focus line
}
Output is:
adderess store in c:9105699 value point by c:a address of c:8af564
why it is storing 'a' in *c instead in c?
I am using gcc compiler 4.4.3.
int *c=12345;
You just made a pointer that points to the (probably) invalid address 12345.
If you pass c (no *) to printf, you're passing the pointer itself. Therefore, printf simply sees the number 12345, and prints that. It has no way of knowing that that's supposed to be a pointer.
If you pass *c, to printf, you're dereferencing the pointer – you're passing the value at memory address 12345.
Since that's not a valid address, the dereference operation will crash (to be precise, will behave undefinededly) before it ever gets to printf.
So my question is as per theoretical concept *str hold the value 12345 but it is not. why?
int *c=12345;
is the same as:
int *c;
c=12345;
It is not the same as:
int *c;
*c=12345;
There is a semantical quirk in the C language here. The * belongs to the declaration, yet it only applies to that specific variable.
You could clarify the fact that * belongs to the declaration by putting it next to the data type:
int* c = 12345; // Don't format your declaration like this,
// see next example as to why
If you do, you will run into trouble when declaring multiple variables in the same statement:
int* a, b, c; // a is a pointer to int, b and c are plain int
// it is the same as:
int *a; int b; int c;
// and **not**
int *a; int *b; int *c;
So, you just have to learn that the * belongs to the declaration. There are no problems caused by this, because you cannot safely assign *c unless you first have assigned a valid address to c.
why it is storing 'a' in *c instead in c?
char *c='a';
printf("%d %c %x", c,*c ,&c); //Focus line
You are declaring a pointer to char that points to memory location 97 (The ascii value of a is 97).
You then try to print the pointer as a number (should print 97, but see below), the value of memory location 97 as a character (c is an invalid pointer at this stage, so the result is undefined, and the address of the pointer c (c is an aout variable located on the stack).
When I compile this code I get a
Warning: initialization makes pointer from integer without a cast
when assigning 97 to the character pointer c.
When I run this code in cygwin I get a Segmentation fault from the undefined behaviour.