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]);
Related
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.
I am attempting to learn C in a little more depth. I have written the code displayed below.
#include "includes.h"
int main() {
char *array[1];
array[0] = "cloud";
char *ll[1];
ll[0] = array[0];
int n = 20, *pointer; // actual and pointer decaration
pointer = &n; // assign the memory address of int n to pointer
printf("the address of the variable in pointer is: %x\n", pointer);
printf("the value of *pointer is %d\n", *pointer);
printf("the value of &pointer is %x\n", &n);
//return 0;
// to access the value provided by a pointer, you would use *pointer
// accessing an array directly
printf("value of array[0] %s\n", array[0]);
printf("address of &array[0] %x\n", &array[0]);
// accessing array through the pointer ll
printf("value of *ll %s\n", *ll);
printf("address of ll %x\n", ll);
printf("pointer: %p\n", (void*) pointer); //inclusion from #chux
}
The header file "includes.h" contains the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#define DEF1 20
#define DEF2 2
Here is the program output, as from my Bash Terminal:
[carl#sparknohss c]$ ./pointers.bin
the address of the variable in pointer is: 4a8c27dc
the value of *pointer is: 20
the value of &pointer is: 4a8c27dc
value of array[0]: cloud
address of &array[0]: 4a8c27f0
value of *ll: cloud
address of ll: 4a8c27e0
pointer: 0x7ffc4a8c27dc
[carl#sparknohss c]$
I see that there is a difference, at least I think, when accessing a pointer that points to a non-array and when accessing a pointer that points to an array. Is there anyone that can explain this in a little more detail?
Also, what is the difference between %x and %p, other than the '0x7ffc' prefix provided by %x? Are there any good resources that I can delve into for a better explanation?
I see that there is a difference, at least I think, when accessing a pointer that points to a non-array and when accessing a pointer that points to an array. Is there anyone that can explain this in a little more detail?
There are some differences when dealing with arrays and pointer objects.
Setting aside your code for a second, assume you have the declaration
int arr[10];
This creates an array arr large enough to hold 10 integers; it's laid out in memory like so:
+---+
arr: | | arr[0]
+---+
| | arr[1]
+---+
...
+---+
| | arr[9]
+---+
One thing becomes obvious here - the address of the first element of the array (&arr[0]) is going to be the same as the address of the whole array object (&arr). The expressions &arr[0] and &arr will have the same value, but their types will be different - the type of &arr[0] will be "pointer to int" (int *), while the type of &arr will be "pointer to 10-element array of int" (int (*)[10]).
Now here's where a wrinkle comes in - except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize another array in a declaration, an expression of type "array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
This means that the expression arr also evaluates to the address of the first element of the array, just like &arr[0] and &arr; it "decays" from type "10-element array of int" to "pointer to int" (same type as &arr[0]).
This is definitely different from how regular pointer variables behave. Given
int *ptr;
the expression ptr does not give you the same value as &ptr - it gives you the value of whatever is stored in ptr.
Going back to your code for a second, in the line
array[0] = "cloud";
the string literal "cloud" is itself an array expression - it has type "6-element array of char" (counting the 0 terminator). Since it is not the operand of the sizeof or unary & operators, nor is it being used to initialize another array in a declaration, the expression is converted from type "array of char" to "pointer to char", and the value of the expression is the address of the first character in the string. Since you declared array as an array of char *, this works; the type of array[0] is char *.
So, why do array expressions "decay" to pointer expressions?
The array indexing operation a[i] is defined as *(a + i) - given an address value, offset i elements (not bytes) from that address and dereference the result. This is a holdover from the B programming language from which C was derived, and which used pointers internally when setting up array objects. C got rid of the internal pointers, but kept the subscript semantics. So, for a[i] to work in C, a first has to be converted to a pointer value. Note that this means you can use the [] operator on pointer types - pointer[0] and *pointer will give you the same result (the value of the thing pointer is pointing to).
So, if you print out the following expressions:
printf( "&array[0] = %p\n", (void *) &array[0] );
printf( "array = %p\n", (void *) array );
printf( "&array = %p\n", (void *) &array );
you should see the same value for all three - the address of the first element of array. If you print out the expression
printf( "array[0] = %p\n", (void *) array[0] );
you should see the address of the first character of the "cloud" string literal.
If you print the expression
printf( "array = %s\n", array );
you should see the string cloud. Remember that the %s conversion specifier expects its corresponding argument to be a pointer to char, and it will print the sequence of characters starting at that address until it sees the 0 terminator.
If you print the expression
printf( "*array[0] = %c\n", *array[0] );
you will see the character c - the first letter in the "cloud" string. Note that *array[0] is the same as array[0][0]. To print l, you'd write
printf( "array[0][1] = %c\n", array[0][1] );
If you print the expressions
printf( "pointer = %p\n", (void *) pointer );
printf( "&pointer = %p\n", (void *) &pointer );
you should definitely see different values since pointer is not an array object.
Also, what is the difference between %x and %p
%x expects its corresponding argument to have type unsigned int, and formats the output in hexadecimal.
%p expects its corresponding argument to have type void *, and formats the output in an implementation-defined manner (often hex, but it doesn't have to be).
You do not want to use %x (or anything other than %p) to print out pointer values. For one thing, a pointer value may be wider than an unsigned int (that's true on my system), so the output will likely be garbled.
I am trying to run this code, but the compiler returns the following warning:
int c=23;
int *const a=&c;
printf("%d",(int)a);
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
printf("%d",(int)a);
You receive a warning because after type mismatch, the compiler must convert it to print it and information will be lost.
If you want to print the physical address of the pointer, use %p and cast the pointer to void *:
printf("%p", (void *) a);
If you want to print the contents of the pointer ( to which it's pointing to), you must dereference it:
printf("%d", *a);
Remember, to access the content, use *. Otherwise you work with the pointer, not its contents. To get the address of a non-pointer variable: &.
You have declared a as a constant pointer, but you are trying to print it as an int. Use the %p specifier in order to print the address of your pointer and cast your pointer as void, like this:
printf ("%p", ( void * ) a);
c represents an address in memory that is the first byte of an integer - in this case the number 23
a represents another address in memory that is the first byte of a pointer - in this case holding the address of c (not the value in c because you used &c which means its address)
To print out a in a meaningfull way printf must use the pointer format %p
If you use these four printf statements:
printf("%p\n", a);
printf("%p\n", &c);
printf("%d\n", *a);
printf("%d\n", c);
you will get something like this:
0x7ffc080a3f24 ('a' contains a pointer which is the address of 'c')
0x7ffc080a3f24 (&c is the address of 'c')
23 (*a, dereferencing the pointer contained in 'a' provides the value held by the address held by 'a')
23 (and 'c' is the value held at the address &c)
Note that you will also get a warning if you do this:
printf("%p\n", (int) a);
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
because you are using the right format specifier for the pointer 'a', but you have cast it to the integer type. Whilst both int and a pointer are 'integers' they are different size integers.
If you ignore the warning and run the code, the value printed is not correct, but you can see that it has been truncated:
0x80a3f24
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:!
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.