typedef char trgm[3];
char test[2][3] = {'a','b','c','d','e','f'};
int main(void)
{
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
return 0;
}
the output of three printf is same. I don't understand why the t and *t are same? what does complier do internal?
There are three paths of interpretation of the same value - the starting address of the memory extent occupied by the array. So dereferencing the value casted to char * you will get the value of the first element of the type char of the array.
You can think of an array variable as containing the memory address of its first element. In your case since the array is a 2D array, the "first element" t[0] is in-fact pointer to the 'first row'. Note that in terms of memory there is no special storage for element t[0] and t[1], it gets converted to appropriate memory offset, but it helps to think that way. Hence when you deference the pointer (*t), you get the same value as you would get for the array variable.
t = [0] --> 'a','b','c'
[1] --> 'd','e','f'
Try this printf("%p %p %p\n", t,*t, t[0]);, you will get same value for all.
When you declare the typedef char trgm[3];, then trgm refers to *an array of char [3]`. This is important.
When you declare trgm *t = test, the pointer t is a pointer to array of char [3]. By setting t = test; you make t a pointer that points to the first row of test (essentially equivalent to test[0]. Since an array variable holds (or points to) the first element of test, both t and test point to the same value. Dereferncing the either the pointer t or test (e.g. *t or *test) will access the first element of test.
Now since t is a pointer to array of char [3], it is a pointer with two-levels of indirection and can therefore be dereferenced twice (as can test). Take test[row][col]. Let's look at the pointer equivalent for the array. test can be written as
*(*(test + col) + row)
(both col and row are 0 when referencing the first element (e.g. test[0][0]) so the above is simply
*(*(test + 0) + 0)
note: anything plus 0 is just that thing again, so it simplifies to:
**test
For t it is just:
(*t)[col] /* to index cols 0 - 2 */
It too can be rewritten as:
*((*t) + col)
With col being zero for the first element, you get
**t
However, t by pointing to the first row, allows pointer arithmetic (e.g. t = t + 1;, or just t++) to update t to point to the second row, and so on.
So, in sum, whether you are looking at test or you are looking at t, both initially reference the address for the first element in test, both are (or can be considered) pointers with two levels of indirection, and dereferencing each once, or twice, will still point at the original element in test. You can use t to access all values in your array, for instance:
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
Which will output:
a, b, c
d, e, f
Lastly, there is no need to make test a global variable. Avoid global variables to reduce the chance of name collision. Declare test in main() and pass it pointer to it to any other function it is required.
Putting that altogether, you could do something like:
#include <stdio.h>
typedef char trgm[3];
int main(void)
{
char test[][3] = {{'a','b','c'},
{'d','e','f'}};
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/p2x3
a
a
a
a, b, c
d, e, f
Look things over and let me know if you have any further questions.
Related
This question already has answers here:
How to change a variable in a calling function from a called function? [duplicate]
(3 answers)
Closed 4 years ago.
void change_it(int[]);
int main()
{
int a[5],*p=1;
void change_it(int[]);
printf("p has the value %u \n",(int)p);
change_it(a);
p=a;
printf("p has the value %u \n",(int)p);
return 0;
}
void change_it(int[]) {
int i=777, *q=&i;
a = q; // a is assigned a different value
}
For starters, when you initialize p, you're giving a pointer the value of 1, when it needs a memory location. NULL uses 0, but that doesn't mean you can -or should- just assign integer values to pointers.
Just as an fyi, you can cast the value of 1 like this:
int a[5], *p = (int *) 1;
There's like -2 reasons for doing this, though, the -1th reason being that the minimal type safety that C provides should be respected, and the -2th being that it makes the code hard to understand for other people.
I'm going to assume what you meant to do was not declare a pointer with an address value of 1 though, and say you meant to declare a pointer that holds a value of 1. Unless you have another variable that holds the value of 1 already, you're going to have to first dynamically allocate the pointer, then set its value.
int* p = malloc(sizeof(int));
*p = 1;
If you had another variable to use, you could instead create the pointer on the stack rather than dynamically allocating it, like this:
int* q;
q = p;
Now, calling the same print function on both would yield this:
printf("p has the value %d\n", *p);
printf("q has the value %d\n", *q);
Output:
p has the value 1
q has the value 1
Addressing your main problem, you need to name the parameter in the change_it function, for example:
void change_it(int arr[])
Your program needs the parameter to be named, otherwise it has no idea of knowing you're trying to reference the array. The a variable you reference in the function is not bound to anything; the compiler will know be able to deduce what you're talking about.
Also, you don't need to redeclare the function prototype in your main function. The reason this is not a compiler error is that you can have as many declarations as you want, but only one definition. Again though, there's no reason to do this.
Another fyi, you don't have to name the parameters in your function prototypes, but it's good practice to both name them and be consistent with the names between the prototypes and the actual implementations so that people reading your code understand what's going on.
Also, you're using the %u specifier for the printf function, when you're not actually using unsigned decimal numbers. You're using signed decimals so you should use %d.
Lastly, your change_it function commits one crucial error preventing it from correctly changing the value of the passed-in array properly: you're setting the array that you passed in to the value of q.
Look at the function in your original code closely (pretend you named the input array a, as it looks like you mean to). You first declare an integer variable i and set its value to 777. Then, you create an integer-pointer variable q on the stack and correctly set its value to i. Note: You're not setting q to the value of i, but rather the address of i.
Why does this small but significant distinction matter? When you set a to q in the next line, you're changing the address of the array, specifically the first element of a five-element integer array, to point to the address of an integer variable. This is bad for a few reasons. First, the array is five integers long, but now it points to a single element. If and when you try to access elements 2-5, you'll get either meaningless garbage or a segmentation fault for trying to access memory you don't own. Even worse, the variable i is allocated on the stack, so when the function change_it exists, the function's data will be popped off the stack, and trying to access the address of i will yield either garbage or a segmentation fault for trying to access memory you don't own. See a pattern?
I'm not really sure how to correct this code, as I'm not sure what you were trying to accomplish, but correcting the aforementioned errors, your code now looks something like this:
#include <stdio.h>
void change_it(int arr[]);
int main()
{
int a[5];
int *p = a; // Equivalent to int *p = &a[0];
printf("a address: %p\n", a); // Should be equal to p
printf("p address: %p\n", p); // Should be equal to a
a[0] = 1;
printf("a[0] = %d\n", a[0]); // 1
printf("p has the value %d\n", *p); // 1
change_it(a);
p = a;
printf("a address: %p\n", a);
printf("p address: %p\n", p);
printf("a[0] = %d\n", a[0]);
printf("p has the value %d \n", *p);
return 0;
}
void change_it(int arr[])
{
int i=777;
arr[0] = i;
// Could be just:
// arr[0] = 777;
}
Output:
p address: 0x7fffc951e0b0
a[0] = 1
p has the value 1
a address: 0x7fffc951e0b0
p address: 0x7fffc951e0b0
a[0] = 777
p has the value 777
Note: Your memory address can and probably will be different from these, all it matters is that p and a are equal in both.
Anyways, hope this helps. Let me know if you have any questions.
Alright, you I believe do not have basic understanding of a function: First lets start with declaration and definition:
void change_it(int[]); // THIS IS DECLARATION
int main ()
{
void change_it(int[]); // THIS IS DECLARATION (duplicate and unnecessary
....
}
void change_it(int[] a) // THIS IS DEFINITION
{
int i=777, *q=&i;
a = q; // a is assigned a different value
}
declaration of the function only needs (you can put parameter name for readability) a parameter type, where as definition has to have name of the parameter because in definition parameters are local variables.
printf("p has the value %u \n",(int)p);
This will print the address of p not the value of p. So this should be
printf("p has the value %u \n", *p);
And finally we get to the body of a function. Where you are depending on somthing that have been locally assigned and putting it back into parameters
void change_it(int[] a)
{
int i=777, *q=&i;
a = q; // a is assigned a different value
}
so q is pointer and you are assigning address of local variable i to it. Well what happens when your program exists the function? i might disappear thus loosing its values and its address, which is assigned to q which means q is loosing its variable and value, and which is assigned to a which might loos its variable because it is pointing to i in your function.
This part here:
int a[5],*p=1;
void change_it(int[]); // Here, doesn't compile
printf("p has the value %u \n",(int)p);
That statement isn't just valid, as far as I know, you can't declare a function inside another function in C.
Also:
void change_it(int[]) // Here, an error
{
int i = 777, *q = &i;
a = q;
}
This function needs an argument, but you supplied only its type (being int[]),
void change_it(int a[]) fixes the problem
Your program does not compile and produce warnings. It would not work as you intended.
1) p is a pointer. To access value which it points to you have to dereference it using * dereference opearator.
2)
void change_it(int[]);
is not needed in the body of main.
3)
the invocation of change_it() seems to have no effect
If you want to change a[0] element inside the function change_it name the passing parameter to a and dereference the q pointer,
The working program may look as this:
#include <stdio.h>
void change_it(int a[]);
int main()
{
int a[5] = {0}; // init all element of `a` to `0`
int *p; // declare int pointer
p = a; // p point to array `a`
// print the first element of array `a`
printf("a[0] has the value %d \n",(int)*p);
// call function change_it, pass `a` as the argument
change_it(a);
printf("a[0] has the value %d \n",(int)*p);
return 0;
}
// change the value of the first element of array `a` to 777
void change_it(int a[]) {
int i=777, *q; // declare int i and pointer
q = &i; // pointer `q` points to the `i` now
a[0] = *q; // a[0] is assigned value = 777;
}
Output:
a[0] has the value 0
a[0] has the value 777
I'm new in programming and learning about pointers in array. I'm a bit confused right now. Have a look at the program below:
#include <stdio.h>
int fun();
int main()
{
int num[3][3]={23,32,478,55,0,56,25,13, 80};
printf("%d\n",*(*(num+0)+1));
fun(num);
printf("%d\n", *(*(num+0)+1));
*(*(num+0)+0)=23;
printf("%d\n",*(*(num+0)));
return 0;
}
int fun(*p) // Compilation error
{
*(p+0)=0;
return 0;
}
This was the program written in my teacher's notes. Here in the main() function, in the printf() function dereference operator is being used two times because num is pointer to array so first time dereference operator will give pointer to int and then second one will give the value at which the pointer is pointing to.
My question is that when I'm passing the array name as argument to the function fun() then why *p is used; why not **p as num is a pointer to array?
Second thing why *(p+0) is used to change the value of zeroth element of the array; why not *(*(p+0)+0)=0 as in the main() function *(*(num+0)+0) is used to change the value of zeroth element?
The whole thing is very confusing for me but I have to understand it anyway. I have searched about this and found that there is a difference between pointer to array and pointer to pointer but I couldn't understand much.
The trick is the array-pointer-decay: When you mention the name of an array, it will decay into a pointer to its first element in almost all contexts. That is num is simply an array of three arrays of three integers (type = int [3][3]).
Lets analyse the expression *(*(num + 1) + 2).
When you mention num in the expression *(num + 1), it decays into a pointer to its first element which is an array of three integers (type = int (*)[3]). On this pointer pointer arithmetic is performed, and the size of whatever the pointer points to is added to the value of the pointer. In this case it is the size of an array of three integers (that's 12 bytes on many machines). After dereferencing the pointer, you are left with a type of int [3].
However, this dereferencing only concerns the type, because right after the dereferencing operation, we see expression *(/*expression of type int[3]*/ + 2), so the inner expression decays back into a pointer to the first array element. This pointer contains the same address as the pointer that results from num + 1, but it has a different type: int*. Consequently, the pointer arithmetic on this pointer advances the pointer by two integers (8 bytes). So the expression *(*(num + 1) + 2) yields the integer element at an offset of 12 + 8 = 20 bytes, which is the sixth integer in the array.
Regarding your question about the call of fun(), that call is actually broken, and only works because your teacher did not include the arguments in the forward declaration of fun(). The code
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
fun(num);
}
would have generated a compile time error due to the wrong pointer type. The code of your teacher "works", because the pointer to the first array in num is the same as the pointer to the first element of the first array in num, i. e. his code is equivalent to
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
//both calls are equivalent
fun(num[0]);
fun(&num[0][0]);
}
which would compile without error.
This example shows a matrix, pointers to the first integers of arrays, and pointer to pointer
#include<stdio.h>
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */
int main()
{
/* matrix */
int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}};
/* three pointers to first integer of array */
int *pnum[3] = {num[0], num[1], num[2]};
/* pointer to pointer */
int **ppnum = pnum;
printf("%d\n", *(*(num+1)+2));
fun(num);
printf("%d\n", *(*(num+1)+2));
pnum[1][2] = 2;
printf("%d\n", *(*(num+1)+2));
ppnum[1][2] = 3;
printf("%d\n", *(*(num+1)+2));
return 0;
}
int fun(int (*p)[3])
{
p[1][2]=1;
return 0;
}
You do not actually need any pointers to print anything here.
Your int num[3][3] is actually an array of three elements, each of which is an array of three integers. Thus num[0][0] = 23, num[1][1] = 0, and so on. Thus you can say printf("%d", num[0][0]) to print the first element of the array.
Pointer to variable:
Pointer is variable which stores the address( of a variable). Every one know that.
Pointer to Array:
An array is a variable which has the starting point(address) of group of same objects.
And the pointer is a variable which stores the starting point(address) of an Array.
For example:
int iArray[3];
iArray is a variable which has an address value of three integers and the memory is allocated statically. And the below syntax is provided in a typical programming languages.
// iArray[0] = *(iArray+0);
// iArray[1] = *(iArray+1);
// iArray[2] = *(iArray+2);
In the above the iArray is a variable through which we can access the three integer variables, using any of the syntax mentioned above.
*(iArray+0); // Here iArray+0 is the address of the first object. and * is to dereference
*(iArray+1); // Here iArray+1 is the address of the second object. and * is to dereference
So simple, what is there to confuse.
The below lines are for your understanding
int iArray1[3];
int iArray2[3][3];
int *ipArray = 0;
ipArray = iArray1; // correct
ipArray = iArray2[0]; // correct
ipArray = iArray2[2]; // correct
int **ippArray = iArray2; // wrong
As per the above last line, compiler will not take it as a valid assignment. So **p is not used.
Pointer arthmatic cannot be applied on double arrays because of the way memory is allocated.
EDITED: Basically, I am trying to determine in a vector, being given one element, what the next element is. The elements are contiguous. The expression below is supposed to pass the first element as the previous element, and it should return a pointer to the second element. I want the distance to return the difference b/w the previous pointer and the first pointer to find where the second element is...
I have this expression:
int next = *(char *)v_next(vec, vec_first(vec));
Then in the function being called, I have this line in order to determine the position of one pointer from another..
void *v_next(const vector *vec, const void *previous) {
...
void *first = cvec_first(cv);
int distance = (char*) &previous - (char*) &first;
However, when I compare the first element and the second element, it returns a distance of 32. If I divide this distance by char*'s size, I get 8. That's clearly way too many bytes to separate one pointer from another and therefore this expression doesn't work out to find the right position...
next = (char*) vec->elems + vec->elemsz + distance;
How can I get the subtraction working properly?
The thing is that you need to substract pointers of proper "undecayed" type (whatever it is in your case). See following example:
#include <stdio.h>
int main(void)
{
int a[] = {1, 2, 3, 4, 5}, *p, *q;
p = a;
q = a + 1;
printf("Corect distance: %d\n", (int) (q - p));
printf("Incorrect distance: %d\n", (int) ((char *)q - (char *)p));
return 0;
}
Note that p and q have to point into the same array, or more precisely (C99 6.5.6 Additive operators):
[...] to elements of the same array object, or one past the last element of
the array object; the result is the difference of the subscripts of the two array elements.
otherwise it's UB. The result of substaction has implementation-defined type ptrdiff_t (that's why I casted result to int).
You're comparing the wrong pointers. &first is the location of the variable first, which is a local variable. Same for &previous. So you're comparing two pointers that has nothing to do with what's in the vector.
From your third statement it looks like you want the offset in bytes. You shouldn't divide it by anything if so. It's given by:
int distance = (char*)previous - (char*)first;
(note that you might want to use ptrdiff_t instead of int depending on your architecture.)
Your statement for next should then work, but it should also be the same as:
next = (char*)previous + vec->elemsz;
I've tried that, but when I use the expression beginning with "int next" above, it only prints 0.
That's because of your first line, where you're only reading a single byte (char):
int next = *(char *)v_next(vec, vec_first(vec));
^^^^^^^^^
You're casting to the wrong type here. You want to cast to the type that's stored in the vector, which I'm guessing is int. So it should read:
int next = *(int *)v_next(vec, vec_first(vec));
I've just read in the book "The C Programming Language" that array is not a variable and saw that assignment of array to pointers (and vice versa) can't be done as a result. So if array is not a variable then what is it?
int numbers[] = {1,2,3}
numbers is not a variable, it is the array name which is nothing but the address of the first element in the array. To verifiy this, look at the address of numbers and the address of numbers[0] by doing this: printf("%p and %p and %p", &numbers, numbers, &numbers[0]); All the the three pointers will have the same values since numbers is nothing but the address of the first element in the array. Therefore numbers is not a variable that contain a pointer or a value since it does not have a dedicated address in the memory to store value in it.
However, look at this pointer variable:
int *pnumbers = numbers;
`printf("%p and %p and %p", &pnumbers, pnumbers, &pnumbers[0]);`
You will notice that &pnumbers has a different address in memory, and that's because pnumber has a dedicated address in the memory where it stores the address of the first element in the array numbers.
Putting the code all together:
#include <stdio.h>
main(){
int numbers[] = {1,2,3};
printf("%p and %p and %p\n", &numbers, numbers, &numbers[0]); // Address of numbers, value of numbers, first element of numbers
int *pnumbers = numbers;
printf("%p and %p and %p\n", &pnumbers, pnumbers, &pnumbers[0]); // Address of pnumbers, value of pnumbers, first element of the array pnumbers is pointing to
}
Output
0xbfb99fe4 and 0xbfb99fe4 and 0xbfb99fe4 // All three have the same address which is the address of the first element in the array
0xbfb99fe0 and 0xbfb99fe4 and 0xbfb99fe4 // The first one is different since pnumbers has been allocated a memory address to store a pointer which is the first element of the array numbers
Array is a data structure containing a number of values, all of which have the same type and array names are non-modifiable l-values(named memory locations)-- it is addressable, but not modifiable. It means that it can't be modified or can't be the left operand of an assignment operator.
int a[10] = {0};
int *p = a; //OK
a++ // Wrong
a = p; // Wrong
It's a placeholder. A symbol to represent a commonly used method of referring to a sequential section of memory. It's not a variable all by itself.
int main(int argc, char** argv)
{
int array[10];
int value'
int* pointer;
value = array[0]; // Just fine, value and array[0] are variables
array[0] = value; // Just fine, value and array[0] are variables
pointer = &array[0]; // Just fine, &array[0] is an address
pointer = array; // Also just fine
//Because the compiler treats "array" all by itself as the address of array[0]
//That is: array == &array[0]
&array[0] = pointer // ERROR, you can't assign the address of something to something else.
array = pointer; // ERROR, array is not a variable, and cannot be assigned a value.
//Also bad, but technically they compile and could theoretically have their use
pointer = value;
pointer = array[0];
array[0] = pointer;
//Intermixing pointers and non-pointer variables is generally a bad idea.
}
array is often treated like a variable because it represents the adddress of (the first item in) that block of memory. But it's not a variable. It doesn't have it's own memory to store anything. People set pointers equal to 'array' because it's a handy convention, compilers know what that means, and it's pretty common.
array is a sequence of elements of the same type. if you assign a pointer to an array, pointer will point to the address of first variable from an array.
int a[10];
int *p;
int *p2;
p = a;
p2 = &a[0];
printf("%d\n", p == p2);
output:
1
I've just read in the book "The C Programming Language" that array is not a
variable and saw that assignment of array to pointers (and vice versa)
Vice versa is allowed... An array is like a constant pointer (you cant change the address it is pointing to). However, you can assign that address to a pointer.
#include <stdio.h>
int main()
{
int x[3] = {1, 2, 3};
int *p = x;
p[0] = 50;
printf("%d", x[0]);
}
This question already has answers here:
Is an array name a pointer?
(9 answers)
Closed 8 years ago.
i have often heard that array and pointers can be used interchangeable in some situation but the two does not mean the same thing so what are the circumstances in which we can use array as a pointer and vice versa.
Arrays and pointers are never the same thing.
However, under certain circumstances, an array name in your code will "decay" to a pointer to the first element. That means you lose information about the size of the array since a pointer doesn't know how many elements it points to (technically, it only points at one though you can advance through a contiguous array if you can tell where the end is, such as with a length or sentinel value).
Situations in which arrays do not behave like pointers are (for example):
when you do a sizeof: for the array, it's the size of the entire array, for a decayed pointer, it's the size of the pointer.
when you want to move through an array: with a real array, you must use indexing while you can simply increment the pointer.
Consider the following code:
#include <stdio.h>
void fn (int arr[]) {
printf ("sz = %d\n", sizeof(arr));
printf ("#4 = %d\n", arr[4]);
arr = arr + 1;
printf ("#4 = %d\n", arr[4]);
}
int main (void) {
int x[] = {1,2,3,4,5,6,7,8,9};
printf ("sz = %d\n", sizeof(x));
printf ("#4 = %d\n", x[4]);
//x = x + 1; // Cannot do this
printf ("#4 = %d\n", x[4]);
puts("=====");
fn(x);
return 0;
}
which outputs:
sz = 36
#4 = 5
#4 = 5
=====
sz = 4
#4 = 5
#4 = 6
You can see from that the sizeof is different and you can actually move the pointer whereas the array name is at a fixed location (you'll get an error if you uncomment the line that tries to increment it).
The name of an array behaves pretty much like a pointer to the first element. That is it's value, although it has other attributes that are different.
This is most obvious when calling a function. If you have:
float sum_floats(const float *x, size_t num_values);
you can call it with:
float three[] = { 1.f, 2.f, 3.f };
const float sum = sum_floats(three, sizeof three / sizeof *three);
Note how three in the function call "decays" into &three[0], i.e. a pointer to the first element in the array. Note also how sizeof three still works, since three really is an array.
Inside the function, the array has decayed into const float *, the type of the function's argument, and you can no longer use sizeof to get the size of the caller's array (since the function has no idea that the caller used an array).
Typically an array is a container for a number of elements of the same type, while a pointer is the memory address for a memory location that contains a specific value.
When you declare an array like this:
int arr[] = {1, 2, 3, 4, 5};
printf("%d", *arr); /* will print 1 */
printf("%d", arr[0]); /* will print 1 as well */
/*or*/
int arr[5];
you are allocating memory for 5 integers. Take care that the array name by itself acts as a pointer to the first element in the array.
You can achieve the same thing using pointers:
int* arr = new int[5];