Will these statements all return an address? - c

Says you had a character array in C. Like this:
char array[];
Now, which of the statements below will print out the address. I know that 1) and 2) will, but does 3) also print out the address?
1) printf("Arrays adress is %x\n", array);
2) printf("Arrays adress is %x\n", &array[0]);
3) printf("Arrays adress is %x\n", &array);

None of them. All of them will print garbage value, i.e, your program's behavior is undefined
EDIT: As OP has changed his question now the answer is:
All of them will print address by using %p specifier and casting each of array, &array and &array[0] with void *.
char array[5]; //let's assume an array of 5 chars
printf("Arrays adress is %p\n", (void *)array);
printf("Arrays adress is %p\n", (void *)&array[0]);
printf("Arrays adress is %p\n", (void *)&array);

Assuming array shall read text and the declaration would be char text[] ="...something ..." and you'd use %p instead of %x and casted the values passed to void*: Yes, some addresses will be printed.

Not really, if you want to print out the memory address (a pointer value), I'd use the correct format:
printf("The address is: %p\n", &array);
For example, %x will just print the hex-value for whatever int is passed as the corresponding argument. Once you've done that, all three statements print out exactly the same:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char foo[] = "Some string";
printf("%p\n%p\n%p\n", (void *)foo, (void *)&foo, (void *)&foo[0]);
return 0;
}
Prints out the same thing, three times.
As H2CO3 kindly pointed out, you will need to cast to a void pointer for printf, though
Usually, an array evaluates to the address of its first element. That's why array, &array and &array[0] all churn out the same value. You can read all about it here

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.

Shouldn't dereferencing a pointer provide the value inside the address that you are referencing to?

my code here basically involves a pointer to a 1-D array of 3 integers, I just don't get the output for the line of code 'printf ("Value at address B[0] is: %d\n",*B);'. Like shouldn't dereferencing pointer B provide me the value to the address that it is referencing to? Is there something wrong with my statement? Thanks, the output didn't give me the value instead it provided me the address :'))
#include<stdio.h>
#include<stdlib.h>
int main (void){
int B[2][3] = {{2,3,4},{5,6,7}};
int (*p)[3] = B;
printf("Address at B[0] is: %d or %d\n", B, &B[0]);
printf ("Value at address B[0] is: %d\n",*B); /*when I dereference pointer B here, shouldn't it give me
the value, why is it that when I execute the code, it gives still gives me the address?*/
printf("B + 1 = %d\n", B+1);
}
B is not a pointer. B is an array of two arrays of three int.
When an array is used in an expression, other than as the operand of size of or unary & or as a string literal used to initialize an array, it is automatically converted to a pointer to its first element.
In printf ("Value at address B[0] is: %d\n",*B);, B is automatically converted to a pointer to its first element. So the result of that conversion is &B[0]. Then * dereferences that address. Since &B[0] is the address of B[0], *&B[0] is B[0].
Since B is an array of two arrays of three int, B[0] is an array of three int. Since it is an array used in an expression, and is not the operand of sizeof or unary & and is not a string literal used to initialize an array, it is automatically converted to a pointer to its first element. The result of that conversion is &B[0][0]. That is the same address as &B[0] but has a different type.
Then printf ("Value at address B[0] is: %d\n",*B); attempts to print this address. However, %d is for converting int values to decimal numerals, whereas *B produces a pointer, not an int. The behavior of this is not defined by the C standard. Sometimes it will print the address or part of it.
To print addresses, convert them to void * and print them using %p:
printf("Address at B[0] is: %p or %p\n", (void *) B, (void *) &B[0]);
printf ("Value at address B[0] is: %p\n", (void *) *B);
printf("B + 1 = %p\n", (void *) (B+1));
If you print **B, that will show the value of the first element:
In **B, B will be converted to a pointer to its first element, &B[0], yielding **&B[0].
Then *&B[0] reduces to B[0], yielding *B[0].
Then B[0] is converted to a pointer to its first element, &B[0][0], yielding *&B[0][0].
Then that reduces to B[0][0].

Warning: pointer is used uninitialized when printing its address

I'm new to learning programming by the way so don't be too harsh. Why exactly am I getting this warning and how do I fix it?
Here's the full code:
#include <stdio.h>
int main()
{
int a; // this declares the 'a' variable
int *ptr_a; // this declares the pointer variable
printf("a:");
scanf("%d", &a);
printf("a is %d\n", a); // this prints the value of 'a' that is read from the keyboard
printf("the address of the pointer is %p\n", ptr_a); // this prints the address of the pointer
ptr_a = &a; // this points the pointer to the 'a' variable
*ptr_a = *ptr_a + 5; // this modifies the 'a' variable with its pointer
printf("the value of the modified a is %d\n", a); // this prints the modified value of 'a'
printf("the address of the modified pointer is %p\n", ptr_a); // this prints the modified address of the pointer
return 0;
}
This line:
printf("the address of the pointer is %p\n", ptr_a); // this prints the address of the pointer
does not print the address of the pointer. It attempts to print the value of ptr_a. Since ptr_a has not been initialized, the compiler warns you that you are using it uninitialized.
If you printed the address of ptr_a, with:
printf("the address of the pointer is %p\n", (void *) &ptr_a);
Then the compiler will not warn use, because this does not use the value of ptr_a (which is not initialized), just its address (which is set when ptr_a is created).
After the line ptr_a = &a;, ptr_a is initialized with a value, and a line like this:
printf("The address of a is %p.\n", (void *) ptr_a);
will print the value without a compiler warning.
The warnings are to take seriously, even though they may seem unnecessary at times, doing so will create good programming habits, you can initialize the pointer to NULL then reassign it later, when you need to:
int *ptr_a = NULL;
However what's triggering the problem here is the fact that you are printing the value of the pointer not its address, which would be perfectly fine as it still has an address even when uninitialized, it only has a value when you assign it the address of a variable or otherwise make it point to some memory location.
If you want to print the address of the pointer you'll need &ptr_a and for good measure, being pedantic I'll admit, cast it to void* as %p specifier expects a pointer to void, not to int:
printf("the address of the pointer is %p\n", (void*)&ptr_a);

passing a pointer address vs pointer to a pointer in C

I'm slightly confused between these two pieces of code:
version 1: (gives warnings after compiling)
int func(int *ptr2)
{
*ptr2 += 1;
}
int main()
{
int a = 5;
int *ptr = &a;
printf("Address of a: %x\n", a);
printf("Before: %x\n", ptr);
func(&ptr);
printf("After: %x\n", ptr);
return 0;
}
Output:
Address of a: 5770a18c
Before: 5770a18c
After: 5770a18d
version 2:
int func(int **ptr2)
{
*ptr2 += 1;
}
int main()
{
int a = 5;
int *ptr = &a;
printf("address of a: %x\n", &a);
printf("Before: %x\n", ptr);
func(&ptr);
printf("After: %x\n", ptr);
return 0;
}
Output:
Address of a: cc29385c
Before: cc29385c
After: cc293860
If I'm understanding pointers in C correctly when we pass by reference, we are creating a pointer to that location. This allows us to change the value at the address held by the pointer through the dereference operator.
However, if we want to change the value held by a pointer, we use a pointer to a pointer. We pass the address of the pointer and create a new pointer to hold said address. If we want to change the value, we use the dereference operator to access our pointer's (defined elsewhere) value.
Hopefully I'm on the right track, but I'm struggling to visualize what's happening with version 1 specifically. Mainly, I'd just like to understand the difference in make-up and output between these two programs. I assume version 1 is still a pointer to a pointer, but why are the incremented values different between both programs? If version 1 is successfully incrementing ptr's value (which I suspect is not), why is that I cannot find code with the same syntax? I think I'm missing something fairly trivial here... Any help is appreciated
Based on your output, you appear to be compiling for a 32-bit system where addresses and int are of that size.
When you increment the value at *ptr with that type being int, it will simply add 1.
When *ptr resolves to an int* then it will increment by sizeof(int) because the value at the current address in this case is 4 bytes long, so we have to increase the address by the number of bytes that an int consumes so that we're pointing at the next int. Note that doing this is only valid if you actually have allocated memory at the subsequent address.
Generally you pass a T** when the callee needs to modify the address to point to - such as say, the callee performs a malloc() to allocate space for the pointer.
&ptr is a pointer to a pointer, but what is passed to func() is a pointer to int converted from &ptr in implementation-defined manner. Then, *ptr2 += 1; is incrementing int and add 1 to what is pointed by ptr2 (the pointer ptr in main(), which eventually have the same reepresentation as `int in your system).
In version 2, the pointer to a pointer is correctly passed to func(). Therefore, pointer aritimetic is performed and the size of int is added to the address.
Note that you invoked undefined behavior by passing data having wrong type to printf(). The correct way to print pointers is like this:
printf("Before: %p\n", (void*)ptr);
As you see, cast the pointer to void* and use %p specifier.

How to pass by reference in this case?

I try to use the change() function to change the content of y.
I want to ask why y cannot change when I remove the * when assigning x to "abc"?
Also, I found that &*x is the same as &y, does that mean the address of pointer x is assigned to be the same as the address of the content that *y pointed to? Also, why &x does not equals to "abc"?
My Code:
void change(char *x) {
*x = "abc";
printf("S3: %x\n", &x);
printf("S4: %x\n", &*x);
}
int main() {
char *y = "def";
printf("S1: %x\n", &y);
printf("S2: %x\n", &*y);
change(&y);
printf("result: %s\n", y);
return 0;
}
There are many issues in your code, to point out some of them
y points to a string literal. Any attempt to modify a string literal is undefined behaviour.
To print an address, use %p format specifier, with a cast to (void*) for the argument, Using incorrect type of argument is undefined behaviour. Similarly, to print a char, you need %c, to print a string you need %s. Read more here
Inside change() function, *x is of type char, and you're trying to assign a pointer (base address of the string literal "abc") to it.
Enough!! Ask your compiler to tell you 'bout the rest. (In other words, please enable compiler warnings and try to fix the reported issues.)
why &x does not equals to "abc"?
Because &x gives address of x not value it points to . To get value you need *x.
y can't be changed because it points to string literals which is constant . Any try to change it will cause UB.
does that mean the address of pointer x is assigned to be the same as the address of the content that *y pointed to?
Pointer x has address of pointer y as you pass in function the address of y as argument.
You have to read more about pointers and parameters passing.
A pointer is a variable that holds the address in memory of another variable.
When you refer to a variable in your code the compiler use the value of such variable, for this reason when you refer to a pointer you'll get its content that is an address.
The operator & give back the address of a variable, so in the snippet:
int a = 10;
int *p = &a;
The pointer p will hold the memory address of variable a. If we use the operator * on p we will get the content of the memory address hold by a:
printf("%d", *p);
Will print 10.
If we write &*p, while it is not fully correct and many compilers will even issue a warning, we are getting the value pointed to by the pointer, and than requiring the address of that content, that is to have back again the address of data that is the content of the pointer.
Now the functions, when you pass a parameter in a function a copy of the variable is pushed on the stack from where will be accessed inside the function.
These values are local and any change made to them is lost when you leave the function. Of course if you pass a pointer, the address of your variable, then change the value using the pointer you can reflect the change on the real variable.
But you made a big error in your code, while you are declaring a pointer to char in your function proto:
void change(char *x)
You are passing change(&y); that is a char ** (y is a char *, &y is a char **). You should have got a lot of warnings for that.
Anyway the concept is correct on the caller side, you pass the address where is stored the address of your string, changing it y will point to the new string. It is perfectly legal because you're updating a pointer with another constant string (not changing a constant string that is illegal).
But you need the address of the pointer to the string, your function must be:
void change(char **x)
{
*x = "abc";
printf("S3: %p\n", (void *)&x);
printf("S4: %p\n", (void *)&*x);
}
int main(int argc, char *argv[])
{
char *y = "def";
printf("S1: %p\n", (void *)&y);
printf("S2: %p\n", &*y);
change(&y);
printf("result: %s\n", y);
return 0;
}
Last use the correct formatting in printf for pointer it is %p.
it should be change(y) not change(&y), change(&y) is address of *y not address in y. So y gives address of first character in a string, where &y gives address to y not address to first string.
HTH

Resources