No More Confusing Pointers - c

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:!

Related

'a' is an array, its content is its address, the address of a[0] is also the address of 'a', yet the content of a[0] is not the address of 'a', how?

PLEASE help I'm tearing my hair out! Does C not know how to print the correct addresses or what? and if that's the case do we just ignore it? I've explained everything in this code:
#include <stdio.h>
int main()
{
int a[] = {0xA, 0xB};
printf("%p", &a); printf(" <---address of 'a'\n");
printf("0000000000%X", a); printf(" <---content of 'a'\n");
printf("%p", &a[0]); printf(" <---address of a[0]\n");
printf("000000000000000%X", a[0]); printf(" <---yet the content of a[0] is not the same as the content of 'a' despite sharing the same memory location\n\n");
return 0;
}
I tried with a regular pointer and its content is an address, its address? a different address. I'm afraid that my foundational understanding of pointers is wrong. Thank you in advance
a is an array, not a pointer. Arrays are not pointers.
In printf("%p", &a);, &a is the address of the array. Properly, this should be printed by converting it to void *, as with printf("%p", (void *) &a);.
In printf("0000000000%X", a);, a is automatically converted to the address of the first element of a. Since this is an address (a pointer in C), it should be printed with %p, not %X, and also should be converted to void *. Printing it with %X can cause various problems. Once printed correctly, the address is generally the same as that for &a, because the array and its first element start at the same place in memory (since the latter is the first part of the former).
This automatic conversion of an array to the address of its first element whenever an array is used in an expression other than as the operand of sizeof, as the operand of unary &, or as a string literal used to initialize an array (in a declaration).
In printf("%p", &a[0]);, &a[0] is the address of the first element of a, effectively the same as a in the prior code.
In printf("000000000000000%X", a[0]);, a[0] is the value of the first element of a. %X is a technically incorrect format for this, as it is for unsigned int, whereas a[0] is int, but the value will commonly be printed anyway, reinterpreted as an unsigned int. Since this is the value of an element, not an address, it naturally differs from the prior outputs.

Where is a[0] pointing at?

Let's say we have an array char a[] = "abcd". When I print the following:
printf("%p\n", a);
printf("%p\n", &a);
printf("%p\n", &a[0]);
printf("%p\n", a[0]);
I am getting the following results:
0061FF1B
0061FF1B
0061FF1B
00000061
which means that a[0] is not pointing at the same memory address as either %a[0] or a. This is really confusing to me. I'd like someone to point out the difference between these pointers, and whether or not a[0] is / decays to a pointer.
a[0] is not pointing anywhere because it isn't a pointer but a char object. You lie to printf and tell it that it is a pointer, when it isn't. That's an undefined behavior bug in your program.
Now as it happens 0x61 is the ASCII code for 'a'.
Regarding the other lines in your code: whenever used in expressions or function calls, arrays "decay" into a pointer to their first element. There are very few exceptions when this decay doesn't happen - using the & address-of operator is one of them.
Therefore: printf("%p\n", a); decays to a pointer to the first element, which is 100% equivalent to printf("%p\n", &a[0]);.
In case of printf("%p\n", &a); the decay does not happen but you get the address of the array itself. In C, an array is nothing but a bunch of elements with no other overhead, so the address of the array will always be the same as the address of the first element.
char a[] = "abcd"
Array a, when used in an expression, will convert to pointer to first element of array i.e. &a[0] (there are few exceptions to this rule).
&a is address of array a which is numerically same as the address of first element of array &a[0] but the difference is in their type. The type of &a[0] is char * whereas the type of &a is char (*) [5].
&a[0] is address of first element of array a.
a[0] is first element of character array a.
which means that a[0] is not pointing at the same memory address as either %a[0] or a. ..........
whether or not a[0] is / decays to a pointer.
a[0] is not a pointer, it is first element of array a which is character 'a'. Note that decay happens when array name is used.
When printing a[0], you should use the format specifier %c. Wrong format specifier in printf() lead to undefined behaviour. Also, format specifier %p expect that the argument shall be a pointer to void. You should type cast pointer argument to void * - printf("%p\n", (void*)a);.
When you compile the code with g++, you will find the following warning
main.cpp: In function ‘int main()’:
main.cpp:7:21: warning: format ‘%p’ expects argument of type ‘void*’, but argument 2 has type ‘int’ [-Wformat=]
printf("%p\n", a[0]);
~~~~^
Here, a and &a[0] point to the address of first item of the string
while a[0] is a char. You print a[0] whose ascii is 0x00000061 with %p.
printf("%p\n", &a[0]);
printf("%p\n", a[0]);
In the first case you correctly print the address of the first element of a.
In the second case you ask printf to print a pointer but you pass it a char.
The char is automatically converted to an int (due to the signature of printf, that contains ...).
The ellipsis notation in a function prototype declarator
causes argument type conversion to stop after the last declared
parameter. The default argument promotions are performed on trailing
arguments
The fact that printf prints 61 (exactly the ASCII code) is because on your computer the pointer to object and the int have the same number of bits or because it has 0s next to integer, where printf reads the pointer value.
But it is undefined behavior to pass printf a type and instrument it print other type.
In C array variable is like address
char a[] = "abcd";
// it is all same
// a == &a == &a[0]
// &(a + 1) == &a[1]
// so roughly say 'a' is pointer to address of first element of array
// and a[0] or a[1] is a value.
// this is more appropriate way to express a[0]
printf("%c\n", a[0]);

How to manipulate variable in function?

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

s[ ] is an array.&s should give address of decayed pointer [duplicate]

This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 6 years ago.
After initialising character array name and address refers to same. s[] is an array. so it decays to pointer s, &s should give the address of pointer s
#include <stdio.h>
int main()
{
char s[]="Get Organised! learn C!";
printf("%u %s\n",&s[2],&s[2] );
printf("%u %s\n",s,s ); /* This line and below line is equivalent*/
printf("%u %s\n",&s,&s ); /* Please Explain */
printf("%u %s\n",s[2],s[2] );
printf("%u %s\n",s[3],s[3] );
return 0;
}
%u is just used to see what is going inside.
Getting rid of undefined behaviour first:
int main() {
char const string [] = "hello";
printf("%p %p\n", (void *) string, (void *) &string);
return 0;
}
You get (probably, that's target dependent) the same address printed here because the first expression is implicitly converted to a pointer to the first element of the array while the second is a pointer to the whole array (which most likely happens to start at its first element)
string == &(string[0]) // this is often called decaying
The type of the expression string (or more precisely the expression it decays to) is char const * whereas the type of &string is char const (*array)[6], so they're not "the same".
The reason that &string is not a pointer to a pointer is simple: The C standard explicitly forbids array expressions prefixed with the address of operator (&) (or inside an sizeof operator) to be implicitly converted to a pointer.
With the below, s is an array 100 of char. When is is passed to printf(), array s is converted to the value and type of the address of first element. So printf() is given a char *.
&s is the address of an array 100 of char. It has an equivalent value as s, yet a different type.
char s[100]="Whatever";
printf(some_format,s);
printf(some_format,&s);
To properly print addresses of variables, literals, cast to (void*) and use "%p". The print out typically lacks any description of the type of the variable.
printf("%p\n",(void*) s);
printf("%p\n",(void*) &s);
Output
0x28cbdc
0x28cbdc
To see an effect of the type difference:
printf("%zu\n",sizeof *(s));
printf("%zu\n",sizeof *(&s));
Output
1
100
#john bode also suggested this earlier.

Similarities and differences between arrays and pointers through a practical example

Given the following code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[1];
int * b = malloc(sizeof(int));
/* 1 */
scanf("%d", &a);
printf("%d\n", a[0]);
/* 2 */
scanf("%d", &b);
printf("%d\n", b[0]);
return 0;
}
the following warnings are obtained when it is compiled (i686-apple-darwin9-gcc-4.0.1):
array.c: In function 'main':
array.c:9: warning: format '%d' expects type 'int *', but argument 2 has type 'int (*)[0u]'
array.c:14: warning: format '%d' expects type 'int *', but argument 2 has type 'int **'
but, why does an execution-error occur in the second printf, meanwhile it works for the first printf?
Even more, why it is obtained the same output if the first scanf is substituted by scanf("%d", a);?
Thank very much in advance
In most contexts, an expression of array type will be implicitly converted from an "N-element array of T" to "pointer to T" and its value will be set to point to the first element of the array. The exceptions to this rule are when the array is an operand of the & or sizeof operators, or if the array is a string literal being used to initialize another array in a declaration.
So how does all that relate to your code?
In the line
scanf("%d", &a);
You are applying the & operator to the array. This suppresses the implicit conversion from "array of T" to "pointer to T" and returns a value of type "pointer to array of T", or T (*)[N] (hence your first warning). Now it turns out that the value of a pointer to an array and the value of a pointer to the first element of the array are the same, they just have different types. So assuming that a is at address 0x0001000:
expression type value note
---------- ---- ----- ----
a int * 0x0001000 implicitly converted to pointer
&a int (*)[N] 0x0001000
&a[0] int * 0x0001000
That's why your first call to scanf() "works"; you're passing the right pointer value, but the compiler is complaining because the type of the expression doesn't match what the function expects. Had you written
scanf("%d", a);
you would not have received any warnings, since the type of a will be taken to be int *, which is what scanf() expects. Note that this is identical to calling
scanf("%d", &a[0]);
As for b...
You explicitly declare b as a pointer to int and assign a block of memory to it. When you apply the & operator to it, what you get back is the address of the variable b with type int ** (hence the second warning), not the address that b points to.
expression type value note
---------- ---- ----- ----
b int * 0x0040000 value contained in b
&b int ** 0x0001000 address of b
For that case, you just pass the undecorated b:
scanf("%d", b);
The array a is placed on the stack, the address for the first element is the same as the address of a. &a[0] and &a is the same address
The array b is allocated with malloc, the address for the storage is on the heap, whereas the address for the pointer b is on the stack. &b[0] is not the same address as &b.
That's why the first scanf and printf works but not the second.
The C-FAQ explains it in much greater detail.
In the first scanf you pass a reference to an array. In C arrays are pointers to a memory block of the allocated type, in your case int * and an expression like a[0] gets translated into *(a + 0) (which btw gives rise to the funny variant 0[a] which will actually compile.) This array is allocated on the stack. The second array is allocated on the heap and the stack contains the pointer variable to that array.
In both cases you do not pass a pointer to the first array entry, but to the array and the pointer to the array respectively.
Your first scanf overwrites that what is the array, as it is allocated on the stack, your value ends up (by luck) in the array.
Your second scanf overwrites the pointer to the array, thereby changing the pointer to a memory address that probably does not exist in your data segment. This results in the execution error.
That's normal ...
First, scanf requires a pointer. "a" and "b" already are pointers !
So :
/* 1 */
scanf("%d", a);
printf("%d\n", a[0]);
/* 2 */
scanf("%d", b);
printf("%d\n", b[0]);
Will work.
Normally /* 1 */ shouldn't work. But gcc transforms "&a" by "a" because "&a" doesn't have any sense.
printf("&a = %p\n", &a);
printf("a = %p\n", a);
printf("&b = %p\n", &b);
printf("b = %p\n", b);
&a = 0x7ffff6be67d0
a = 0x7ffff6be67d0
&b = 0x7ffff6be67c8
b = 0xb0b010
You can't take the adress of a. But b is a "normal variable" of type pointer, and thus you can take it's address by "&b".
On /* 2 */ you're putting the value entered by the user in b and thus, *b (or b[0]) will crash unless the user will enter a valid readable memory address.
In your case what is happening is that you are passing both variables a and b with the & operator to the scanf function. What this operator does is "ask" the memory address of the variable and pass that address to the scanf function. But, as both of your variables are pointers, what they have indeed is an memory address, so when you pass &a or &b you are passing the memory of the pointer, not the memory address that it holds.
Example:
int x;
int *ptr;
x = 10;
suppose the memory address of x is 1000. You are storing the number 10 at the memory address 1000. Now you do this:
ptr = &x;
You are storing the address 1000 in the pointer. But 1000, apart being an address, is a number itself, so the pointer, as does x, still needs a memory address to store that information. Suppose the pointer memory location is 1004. Now look the example:
*ptr == 10; //x content
ptr == 1000 //x memory address
&ptr == 1004 // ptr memory address.
So if you want to pass to scanf the variable x, but using the pointer, you need to pass the x address stored in it
scanf("%d", ptr);
Just to ilustrate another example of pointers and vectors
int main
{
int vet[5];
int *ptr;
ptr = vet;
for(int i = 0; i < 5; ++i)
{
scanf("%d", (ptr+i) );
}
}
Here you can read the vector using the pointer. Also, using pointer arithmetics you can iterate over the memory addresses of the vector.

Resources