What does ((short *)((((char *)(&arr[1]))+8))[3]=100; do? - c

...
int arr[5];
arr[3]=128;
((short *)((((char *)(&arr[1]))+8))[3]=100;
...
Above is part of a pretentious code.
What does
((short *)((((char *)(&arr[1])) + 8))[3] = 100
the line do? The following is my thought assuming char is 1 byte and int is 4 byte.
arr will look like arr[0], arr[1], arr[2], arr[3], arr[4] in memory with each 4 bytes. &arr[1] points to arr[1]. (char *)(&arr[1]) is treating arr[1] value 4 bytes as char each of 1 byte.
What is the function part of (char *)(&arr[1]) and ((char *)(&arr[1])) + 8 individually?

((short *)((((char *)(&arr[1])) + 8))[3] = 100
&arr[1]: is the address of the second int in arr (1*sizeof(int) from start).
((char *)(&arr[1])) : converts int address to a char address
(((char *)(&arr[1])) + 8) : adds 8 bytes to the char address
((short *)((((char *)(&arr[1])) + 8)): converts the char address to a short address
((short *)((((char *)(&arr[1])) + 8))[3]: treats the short address as a beginning of an array of storts and goes to the third element in this array (3 * sizeof(short) bytes).
((short *)((((char *)(&arr[1])) + 8))[3] = 100; : assigns 100
*((short*)(((char*)arr) + 1*sizeof(int) + 8 + 3*sizeof(short))) = 100;
The size of an int varies depending on processors but is often 4 bytes.
The size of a short varies depending on processors but is often 2 bytes.
*((short*)(((char*)arr) + 18)) = 100;

Let's split it up (ignoring unneeded brackets):
int* p0 = &arr[1];
char* p1 = (char *)p0;
char* p2 = p1 + 8;
short* p3 = (short *)p2;
p3[3] = 100;
Your arr array has 5 times an 4-bytes integer = a block of 20 bytes.
p0 points to the address of the second integer, so byte at index 4.
p1 stores p0 as address to chars / bytes.
p2 increases the value of p1 by 8 (chars) = points to byte at index 12.
p3 changes p2 to pointer type of 2-bytes (short) integer.
Last line points to fourth short (integer) value which means an address increment by 3 * 2 bytes = now we're at byte index 18 of arr. There we assign value 100 as the last two bytes (index 18 & 19) of our available memory.
In short:
((short *)arr)[9] = 100;
Full example:
#include <stdio.h> // printf
int main(void) {
// Initialize zero-filled memory
int arr[5] = {0};
// Write value 100 to last 2 bytes
((short*)arr)[9] = 100;
// Print memory
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
printf("%d ", arr[i]); // 0 0 0 0 6553600
}

it can be translated to:
short *ptr = (short *)(arr + 1 + 8 / sizeof(*arr)); // or &arr[1 + 8 / sizeof(*arr)]
ptr[3] = 100;

Related

How pointer adds extra value in printf?

#include <stdio.h>
int main() {
int *const volatile p=5;
printf("%d",5/2 + p);
return 0;
}
Without pointer, output is 7 and if I add pointer then the output of the answer is 13. Kindly give the step by step explanation of this program.
The code is invalid. The type of 5/2 + p is int *, while %d requires an int.
Kindly give the step by step explanation of this program.
5/2 + p = // 5/2 is equal to 2
2 + p = // p has type int
2 * sizeof(int) + (char*)p = // p is 5
2 * sizeof(int) + 5 = // sizeof(int) if 4 on your platform
2 * 4 + 5 =
13

In the given example for finding the value " pp-p" on line 5 why the values are divided by 2 in the explanation?

#include<stdio.h>
void main ()
{
int a[10] = {100, 206, 300, 409, 509, 601}; //Line 1 array declared
int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; //Line 2 pointer to the array
int **pp = p; //Line 3 double pointer initialized
pp++; // Line 4 double pointer incremented
printf("%d %d %d\n",pp-p,*pp - a,**pp); // Line 5
*pp++; // Line 6
printf("%d %d %d\n",pp-p,*pp - a,**pp); // Line 7
++*pp; // Line 8
printf("%d %d %d\n",pp-p,*pp - a,**pp); // Line 9
++**pp; // Line 10
printf("%d %d %d\n",pp-p,*pp - a,**pp); // Line 11
}
/* Line number 5 contains an expression which prints three values, i.e., pp - p, *pp - a, **pp. Let's calculate them each one of them.
pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1, i.e., 1 will be printed.
pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1, i.e., 1 will be printed.
pp = 302, *pp = 202, *(*pp) = 206, i.e., 206 will be printed. */
What you see there is basic pointer arithmetics. That's just how adding and substracting to and from pointers works in C.
Let's start with an array:
int a[10] = {100, 206, 300, 409, 509, 601};
You can access these elements using array syntax:
a[0] = xy;
a[2] = 1;
This is identical to the following syntax using pointer arithmetics:
*a = xy;
*(a+2) = 1;
You can see that you can add an index n to access the nth element of your array. For obvious reasons this does not just add the index to the address. Each element has a certain size.
Therefore the rules for arithmetics tell us that the address is adjusted by n bytes, but by n data objects.
How many bytes we need to add/subtract is derived from the size of each object.
For a it is sizeof(int), for p it is sizeof(int*).
The result of adding a number to a pointer is a pointer again. Using normal math rules, you can subtract 2 pointers (if they point into the same array) and get a number which is (again) the number of objects, not the number of bytes.
This means &a[2] - &a[1] == 1. This is true for any size.
Now we look at your code:
int **pp = p;
pp++;
This is same as pp = &p[1] which is pp=p+1. And hence *pp==p[1]==a+1
Now print it:
printf("%d %d %d\n",pp-p,*pp - a,**pp);
Apply the rules from above:
pp-p == p+1 - p == 1
*pp-a == p[1] - a == a+1 - 1 == 1
**pp == *p[1] == *(a+1) == a[1] = 206
==> 1 1 206

Not getting the expected results at pointer increment

Pointer increment not giving the right value, it points to indeterminate address.
Want to know why *p++= <value> not pointing to the value I want instead it points to something else
My code:
void run_exe() {
int i;
uint8_t buf[20] = {"0"};
uint8_t *p = NULL;
uint8_t tx_buf[4] = {1,1,1,1};
p = buf;
*p++ = 0x14;
*p++ = 0x20;
*p++ = 0x30;
*p++ = 0x40;
*p++ = 0x50;
*p++ = 0x60;
memcpy( p+6, tx_buf, sizeof(tx_buf));
// ARRAY_SIZE: is the macro just my array length.
for (i = 0; i < ARRAY_SIZE(buf); i++) {
printf("%d ", *(p+i));
}
}
I'm printing the decimal value of HEX but at least I'm expecting the correct value but I get indeterminate value.
I'm expecting the output like this.
14 20 30 40 50 60 1 1 1 1 0 0 0 0 0 0 0 0 0
Output:
0 0 0 0 0 0 1 1 1 1 0 0 0 0 255 127 0 0 0
You need an auxiliary pointer,
uint8_t *ptr;
p = buf;
ptr = p;
*p++ = 0x14;
and so on, because the ++ will modify the pointer's value.
Then,
for (i = 0; i < ARRAY_SIZE(buf); i++) {
printf("%d ", ptr[i]);
}
The ++ post-increment or pre-increment operator, makes the pointer p point to p + 1 after the expression is evaluated, so your p is NOT pointing to buf when you attempt to print it.
EDIT: Of course you can just do this too,
for (i = 0; i < ARRAY_SIZE(buf); i++) {
printf("%d ", buf[i]);
}
but I think the original answer explains the reason which is the important thing.
EXTRA: Also, I am 99.9% sure that this is wrong
uint8_t buf[20] = {"0"};
you meant,
uint8_t buf[20] = {0};
your compiler might be showing you a warning for this initialization which is faulty, because "0" has pointer type and even though it's convertible to a integer type, it mostly certainly doesn't fit a uint8_t so you have a overflow issue there.

copying integers from char array depending on number of bytes in C

I have one character array of 8 bytes containing integer values. I need to copy the 1 byte to one integer variable, next 4 bytes to different integer variable, next 3 bytes to another integer variable.
I have used "memcpy" but the results are not proper.
My try:
unsigned char bytes[8];
int Data1 = 32769;
int Data2 = 65535;
int logic1 = 0;
int logic2 = 0;
int logic3 = 0;
memcpy(&bytes[0], &Data1, sizeof(Data1));
memcpy(&bytes[4], &Data2, sizeof(Data2));
//Value of bytes[] array after this operation is
//bytes[0] = 1
//bytes[1] = 128
//bytes[2] = 0
//bytes[3] = 0
//bytes[4] = 255
//bytes[5] = 255
//bytes[6] = 0
//bytes[7] = 0
memcpy(&logic1,&bytes,1);
memcpy(&logic2,&bytes + 1,4);
memcpy(&logic3,&bytes + 5,1);
My output should be :
logic1 = bytes[0]
logic2 = bytes[1] to bytes[4]
logic3 = bytes[5] to bytes[7]
I think you meant
memcpy( &logic1, &bytes[0], 1 );
memcpy( &logic2, &bytes[1], 4 );
memcpy( &logic3, &bytes[5], 3 );
Note that &bytes is a pointer to the whole array, so &bytes + 1 points beyond the end of the array, and &bytes + 5 is way beyond the end of the array. Hence you get undefined behavior, and unexplainable results.

Exam Q&A that I don't understand [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
The following code prints out 5. Can someone explain it to me? I think I am mostly confused about the math; for example, using '0' instead of 0 and how I can do that math on paper...
#include <stdio.h>
int main (int argc , char * argv [])
{
char * c_pt ;
int n = 0;
if( argc == 2)
{
c_pt = argv [1];
while (* c_pt )
{
if (* c_pt < '0' || * c_pt > '1') break ;
n = n*2 + * c_pt - '0';
c_pt ++;
}
printf ("%d\n", n);
}
}
When you access the characters in a string containing digits you might get the character '0' or '1' for example. But the integer value of '0' is 48 and the integer value of '1' is 49 so if you want to turn them into the integers 0 and 1 for arithmetic you need to substract something. You could subtract 48 but then the next person that reads your code has no idea why you did that. So nornally you subtract the character represented by the value: '0' - '0' = 0 and '1' - '0' = 1
This particular program reads a string containing a binary number from the command line (so the string contains the characters '0' and '1') and converts that binary number to a decimal number by first converting the '0' and '1' at *c_pt to 0 and 1 and then adding it to the decimal number being built in n. It does that by starting with 0 and then on each iteration multiplying the number by two (which just shifts everything left one bit) and then adding the next digit. So if the string contained 10101 it would follow these steps:
number = 0
input = 10101
pointer = ^
number = number*2 + *pointer = 0*2 + ('1'-'0') = 0*2 + 1 = 1 (in binary: 1)
input = 10101
pointer = ^
number = number*2 + *pointer = 1*2 + ('0'-'0') = 1*2 + 0 = 2 (in binary: 10)
input = 10101
pointer = ^
number = number*2 + *pointer = 2*2 + ('1'-'0') = 2*2 + 1 = 5 (in binary: 101)
input = 10101
pointer = ^
number = number*2 + *pointer = 5*2 + ('0'-'0') = 5*2 + 0 = 10 (in binary: 1010)
input = 10101
pointer = ^
number = number*2 + *pointer = 10*2 + ('1'-'0') = 10*2 + 1 = 21 (in binary: 10101)
void main ( void )
{
int a[] = {22, 33,44};
'a' is a static array (or string) of 3 int, 22, 33, and 44.
int *x = a;
'x' is an int pointer, initialized to point to the same static array as 'a'.
printf (" sizeof ( int )=% lu ", sizeof (int ));
Prints the number of bytes [4] required to represent an int type on this system.
printf ("x=%p, x [0]=% d\n", x, x [0]);
Prints the memory address where the int pointer 'x' is currently pointing[0x7fff29af6530],
then also prints the integer value [22] stored in the [4] bytes starting at that address.
(Note: 'x[0]' is the same as '*x').
x = x + 2;
x [0x7fff29af6530]
+2 + 8 (or (2 * 4) or (2 * sizeof(int)))
---- ----------------
new x [0x7fff29af6538]
Advance the pointer 'x' 8 bytes.
The effect on 'x' is that it will now be pointing at its original memory address plus '(2 * sizeof(int))' bytes. 'a[2]' resolves to the same location.
printf ("x=%p, x [0]=% d\n", x, x[0]);
Prints the memory address where the int pointer 'x' is currently pointing [0x7fff29af6538]
then also prints the integer value [44] stored in the [4] bytes starting at that address.
Hence; 'x' now resolves to the same address as '&a[2]'; and '*x' resolves to the same number as 'a[2]'.
}

Resources