C Simple Arrays & Pointers - c

int a[] = {10, 15, 20, 25};
int b[] = {50, 60, 70, 80, 90};
int *x[] = {a, b};
int *y[] = {a + 2, b + 3};
int *p;
int *q;
int **r;
p = a;
q = y[1];
r = &q;
*p = &p[3] - y[0];
r[0][1] = **r - y[0][1];
What are the contents of a and b at the end?
I figured out that *p is a[0], and &p[3] - y[0] is just 3 - 2, so a[0] = 3 - 2 = 1. Therefore, a[] = {1, 10, 15, 20} (correct me if I am wrong), but b[] is where I get lost. I have no idea how the last line of the code works. No idea on what r[0][1] refers to, so getting the contents for b[] is confusing. P.S. this is for C.

Remember that the identity *(p + k) == p[k] (or p + x == &p[k]) means that you can always rewrite dereferencing as indexing and vice-versa, so if an expression is confusing you can try a different form and see if it makes more sense.
I personally find indexing easier to reason about:
Since r = &q, both r[0] and *r are the same as q:
q[1] = *q - y[0][1];
or
q[1] = q[0] - y[0][1];
q is y[1] gives:
y[1][1] = y[1][0] - y[0][1];
y[0]is a + 2 and y[1] is b + 3:
(b + 3)[1] = (b + 3)[0] - (a + 2)[1];
which is
*(b + 3 + 1) = *(b + 3 + 0) - *(a + 2 + 1);
which is
*(b + 4) = *(b + 3) - *(a + 3);
which is
b[4] = b[3] - a[3];
that is,
b[4] = 80 - 25;

The line int **r; declares a pointer to an int *. In other words, r is a pointer to a pointer to an int. If you recall that the syntax x[y] is equivalent to *(x + y), you might get an idea for what r[0][1] does.
r[0][1] --> *((*(r + 0)) + 1)
Keeping in mind that r[0][1] is on the LHS of the assignment operator, you are storing to that memory location.

Related

subtracting two pointers(arrays), (C language) [duplicate]

This question already has answers here:
Pointer Arithmetic In C
(2 answers)
Pointer subtraction confusion
(8 answers)
Closed 4 years ago.
int vector[] = { 28, 41, 7 };
int *p0 = vector;
int *p1 = vector + 1;
int *p2 = vector + 2;
I know result of
printf("%p, %p, %p\n", p0, p1, p2);
is ex) 100, 104, 108
but why is the result of
printf("p2-p0: %d\n", p2 - p0);
printf("p2-p1: %d\n", p2 - p1);
printf("p0-p1: %d\n", p0 - p1);
is 2, 1, -1
not 8, 4, -4????????
when you subtract to pointers (of the same type else no sense) that computes the difference as indexes, not the difference of the addresses :
type * p1 = ...;
type * p2 = ...;
(p1 - p2) == (((char *) p1) - ((char *) p2)) / sizeof(type)
It is the same when you do vector + n, that gives the address of the element rank n, not ((char *) vector) + n. So
type * p = ...;
int n = ...;
((char *) (p + n)) == (((char *) p) + n * sizeof(type))

C Pointers Past Paper

I'm looking at a past paper for a course I'm doing at university, and there is always a question about C pointers.
I reckon I have a reasonable grasp of how they work, however this is the question that is confusing me:
Consider running the C program fragment:
int x[4] = {0,2,4,6};
int *y;
y = &x[2];
*(x + 2) = y[1] + 1;
What is the value of the expression *y afterwards?
(a) 2
(b) 4
(c) 5
(d) 7
(e) 8
Now, in the answers to said question, it says the answer is d.
I'm super confused, seeing as:
The value of x is not declared, so I'd have thought it would be impossible to evaluate x+2
y isn't an array, so how can y[1] be evaluated?
Why is 7 the correct answer here?
x is the 4-element array. *x references the first element in that array, and *(x + 2) references the 3rd element.
*y points at index 2 (3rd element) in the x array (y = &x[2])
the final assignment sets the 3rd element of the original x array ( *(x + 2) ) to the value of y[1] + 1. since y is initialized to point at the 3rd element, y[1] will point at the final element of the original x array.
6 + 1 is assigned to the 3rd element of the x array, which *y refers to.
Things to note:
*(x + 2) is exactly the same as x[2].
&x[2] is exactly the same as &(*(x + 2)) which is the same as x + 2.
So knowing that, let's rewrite the problem:
int x[4] = {0,2,4,6};
int *y = &x[2];
*(x + 2) = y[1] + 1;
And some more rewriting:
int x[4] = {0,2,4,6};
int *y = x + 2;
x[2] = *(y + 1) + 1;
Now, let's substitute y directly into the last equation:
int x[4] = {0,2,4,6};
int *y = x + 2;
x[2] = *((x + 2) + 1) + 1;
And clean it up:
int x[4] = {0,2,4,6};
int *y = x + 2;
x[2] = x[3] + 1;
So now, let's look at the problem:
x[2] is updated with the value of x[3] + 1
So x[2] is now 7.
So x == {0, 2, 7, 6}
y still points at the value at x + 2.
So *y == 7
Lets break it down:
int x[4] = {0,2,4,6};
x [0] = 0
x [1] = 2
x [2] = 4
x [3] = 6
int *y; Pointer to an integer so y could point to any location in x
x [0] = 0 // <-- y ?
x [1] = 2 // <-- y ?
x [2] = 4 // <-- y ?
x [3] = 6 // <-- y ?
y = &x[2]; Now we have specified that y points to x[2]
x [0] = 0
x [1] = 2
x [2] = 4 // <-- y (or y[0])
x [3] = 6
*(x + 2) This is the same as x[2] so:
x[2] = y[1] + 1;
x [0] = 0
x [1] = 2
x [2] = 4 // <-- x[2]
x [3] = 6 // <-- y[1]
y[1] is 6, so y[1] + 1 = 7
Note that y[1] is the same as *(y + 1). We take the address y points too, add to it the size of one integer and obtain the contents of what it now points to.
Let consider the code step by step.
Pointer y is initialized by the address of the third element of the array (indices start from 0)
y = &x[2];
So y points to 4. So x[2] and y[0] are equivalent expressions
y[1] is the next element after y[0] that is it is 6.
y[1] + 1 will be equal to 7
*( x + 2 ) is the same as x[2] So x[2] will be set to 7. At the same time y also points to
x[2]. So *y will be equal to 7.
The key components here are that the index operator returns y1 an actual int not an address. The same for the dereference operator *(x + 2).
int a = y[1]; // a = the value of the int after y[0]
int b = *(x + 2); // b = the value of x[2] note that the index operator is just shorthand, y[1] just means *(y + 1)
// int* c = y[1]; NOT LEGAL assignment of an int to an int*
// int* d = *(x + 2); NOT LEGAL assignment of an int to an int*
I've added a table here to hopefully help clarify:

Not understanding the calculation

I have following C program, and I'm not understanding the output of the following program.
#include <stdio.h>
int main()
{
int a,b, *p1, *p2, x,y,z;
a=12;
b=4;
p1=&a;
p2=&b;
x=*p1 * *p2-6;
y=4* - *p2 / *p1+10;
printf("y=%d", y);
return 0;
}
The output of the program is 9. But what is the meaning of 4*?
What is the meaning of 4*
The * there is the multiplication operator. Only one operand, 4, is shown in that extract. The full multiplication is:
4* - *p2
which is more clearly written as
4 * -(*p2)
Write out the expression, substituting the values. We can ignore x since it is not used. Which leaves us:
y= 4* - *p2 / *p1+10;
And *p2 is b which is 4. And *p1 is a which is 12. So the expression is:
y = 4 * -4 / 12 + 10;
And this evaluates as:
y = ((4 * -4) / 12) + 10;
Which is
y = (-16 / 12) + 10;
Which is
y = -1 + 10;
The spacing in this line might be causing confusion:
y=4* - *p2 / *p1+10;
This is equivalent to:
y = 4 * (-*p2) / *p1 + 10;
but the spacing makes it look like a subtraction.
The code
4* - *p2
means
4 * (-*p2)
So * means simple multiplication here.
Get familiar with the C precedence and associativity table:
The statements will be evaluated like this (parentheses added for clarity):
x = ((*p1) * (*p2)) - 6;
x = ((12) * (4)) - 6
x = (48) - 6
x = 42
y = (4 * (-(*p2)) / (*p1)) + 10;
y = (4 * (-4) / (12)) + 10
y = (-16 / 12) + 10
y = -1 + 10
y = 9

How does the int and char pointer affect my print out here?

so here is the code, till the 4th print out I easily followed it, but at the 5th print out, I don't understand
why its "5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302 "?
I have commented the line in the code which I don't understand. I look forward to your response.
"#include <stdio.h>
#include <stdlib.h>
void
f(void)
{
int a[4];
int *b = malloc(16);
int *c = 0;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
//I DONT UNDERSTAND WHAT THIS LINE BELOW DOES
c = (int *) ((char *) c + 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
int
main(int ac, char **av)
{
f();
return 0;
}
output:
1: a = 0x7fff65fdcb90, b = 0x1065007e0, c = 0x0
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
6: a = 0x7fff65fdcb90, b = 0x7fff65fdcb94, c = 0x7fff65fdcb91
Let's start with the basics.
c is a pointer to an array of ints.
Let this be a:
[00000000][00000000][00000000][00000000]
Every two digits is a byte, and we assume that sizeof(int) is 4 in our example, so every element in a has 4 bytes, or 8 digits.
Now, c is a pointer to the first element in a.
Let's have a look at the expression in question:
c = (int *) ((char *) c + 1);
Obviously, c is changed here, but what exactly happens is:
c is cast from int* to char*
the result of the cast is incremented, resulting in sizeof(char) being added to c. Since sizeof(char) is 1, c is incremented by 1 and points to the second byte of an element in a.
the result is cast back to int*, and reassigned to c. This second cast is actually not needed.
So, ignoring all the other code, we start from this:
a : [00000000][00000000]...
^
c -|
And go to this:
a : [00000000][00000000]...
^
c ---|
As Daniel pointed out below, if c is not correctly aligned for a pointer of type int*, you get undefined behaviour, which should be avoided.
c is a pointer-to-int, so normally c+1 refers to the address which is sizeof(int) further along in memory - usually 4 bytes on a 32-bit system.
But you cast c to char* - that is, pointer-to-char. Now, char is only 1 byte long, so (char *)c + 1 refers to the memory location 1 byte further on than c; which is in the middle of the int at c.
You then cast the result back to an int* and write 500 into it. So what you're doing is (probably) writing the 4-byte representation of 500 over the last 3 bytes of a[1] and the 1st byte of a[2]. Exactly what effect that will have depends on the endianness of your system, but that's basically what's going on.

Array subscript is not an integer

following this previous question Malloc Memory Corruption in C, now i have another problem.
I have the same code. Now I am trying to multiply the values contained in the arrays A * vc
and store in res. Then A is set to zero and i do a second multiplication with res and vc and i store the values in A. (A and Q are square matrices and mc and vc are N lines two columns matrices or arrays).
Here is my code :
int jacobi_gpu(double A[], double Q[],
double tol, long int dim){
int nrot, p, q, k, tid;
double c, s;
double *mc, *vc, *res;
int i,kc;
double vc1, vc2;
mc = (double *)malloc(2 * dim * sizeof(double));
vc = (double *)malloc(2 * dim * sizeof(double));
vc = (double *)malloc(dim * dim * sizeof(double));
if( mc == NULL || vc == NULL){
fprintf(stderr, "pb allocation matricre\n");
exit(1);
}
nrot = 0;
for(k = 0; k < dim - 1; k++){
eye(mc, dim);
eye(vc, dim);
for(tid = 0; tid < floor(dim /2); tid++){
p = (tid + k)%(dim - 1);
if(tid != 0)
q = (dim - tid + k - 1)%(dim - 1);
else
q = dim - 1;
printf("p = %d | q = %d\n", p, q);
if(fabs(A[p + q*dim]) > tol){
nrot++;
symschur2(A, dim, p, q, &c, &s);
mc[2*tid] = p; vc[2 * tid] = c;
mc[2*tid + 1] = q; vc[2*tid + 1] = -s;
mc[2*tid + 2*(dim - 2*tid) - 2] = p; vc[2*tid + 2*(dim - 2*tid) - 2 ] = s;
mc[2*tid + 2*(dim - 2*tid) - 1] = q; vc[2 * tid + 2*(dim - 2*tid) - 1 ] = c;
}
}
for( i = 0; i< dim; i++){
for(kc=0; kc < dim; kc++){
if( kc < floor(dim/2)) {
vc1 = vc[2*kc + i*dim];
vc2 = vc[2*kc + 2*(dim - 2*kc) - 2];
}else {
vc1 = vc[2*kc+1 + i*dim];
vc2 = vc[2*kc - 2*(dim - 2*kc) - 1];
}
res[kc + i*dim] = A[mc[2*kc] + i*dim]*vc1 + A[mc[2*kc + 1] + i*dim]*vc2;
}
}
zero(A, dim);
for( i = 0; i< dim; i++){
for(kc=0; kc < dim; k++){
if( k < floor(dim/2)){
vc1 = vc[2*kc + i*dim];
vc2 = vc[2*kc + 2*(dim - 2*kc) - 2];
}else {
vc1 = vc[2*kc+1 + i*dim];
vc2 = vc[2*kc - 2*(dim - 2*kc) - 1];
}
A[kc + i*dim] = res[mc[2*kc] + i*dim]*vc1 + res[mc[2*kc + 1] + i*dim]*vc2;
}
}
affiche(mc,dim,2,"Matrice creuse");
affiche(vc,dim,2,"Valeur creuse");
}
free(mc);
free(vc);
free(res);
return nrot;
}
When i try to compile, i have this error :
jacobi_gpu.c: In function ‘jacobi_gpu’:
jacobi_gpu.c:103: error: array subscript is not an integer
jacobi_gpu.c:103: error: array subscript is not an integer
jacobi_gpu.c:118: error: array subscript is not an integer
jacobi_gpu.c:118: error: array subscript is not an integer
make: *** [jacobi_gpu.o] Erreur 1
The corresponding lines are where I store the results in res and A :
res[kc + i*dim] = A[mc[2*kc] + i*dim]*vc1 + A[mc[2*kc + 1] + i*dim]*vc2;
and
A[kc + i*dim] = res[mc[2*kc] + i*dim]*vc1 + res[mc[2*kc + 1] + i*dim]*vc2;
Can someone explain me what is this error and how can i correct it?
Thanks for your help. ;)
mc is of type double. It has to be integral type
mc is pointer to double.
A[mc[2*kc + 1]
In above, you are indexing A with a value in mc (double array). And, there are other similar cases. If you are sure of the values, cast to int
Your declaration of mc:
mc = (double *)malloc(2 * dim * sizeof(double));
And then you use mc multiple times in your array access. For example:
A[mc[2*kc + 1] ...]
Can you change mc to be an int array instead of a double?
Looks like you're using entries in mc, which are doubles, as a part of array subscripts, thus making the entire subscript a double.
If you meant to do this, try casting back to an integer. I don't know what the context of this problem is, but I'd take a real good look at what you're doing to ensure you really want to use the contents of mc as a subscript.
The compiler is complaining because the expression you use as an array index evaluates to type double.
In other words, the expression:
mc[2*kc] + i*dim
...will give you a result which is of type double. You may want to look into the rules for usual arithmetic type conversions in C if you don't understand why this expression evaluates to a double.
The problem is that array indices must be integral types, like int or long. This is because the array subscript operator in C is basically shorthand for pointer arithmetic. In other words, saying array[N] is the same as saying *(array + N). But you can't do pointer arithmetic with non-integral types like float or double, so of course the array subscript operator won't work that way either.
To fix this, you'll need to cast the result of your array-indexing expression to an integral type.
mc is an array of doubles, and floating point values cannot be used to index arrays. I notice that nowhere in your code do you assign anything other than integers to mc. You should consider changing mc's type to an array of integers.

Resources