Reputation: 13
I have the following piece of C code which is showing a weird result. S_data is a struct datatype. Could someone help me to know the reason for this
int i;
typedef struct
{
uint8_t D[19];
uint32_t *D_ptr[19];
} sys_data;
code :
for (i = 0; i < 20; i++) {
S_data.D[i] = 0;
console("%d",S_data.D[i]);
S_data.D_ptr[i] = &S_data.D[i];
}
for ( i = 0; i <20; i++) {
console("Value of var[%d] = %d\n", i, *S_data.D_ptr[i] );
console("Address of var[%d] = %u\n", i, S_data.D_ptr[i] );
}
output :
Address of var[0] = 536872044
Value of var[1] = 0
Address of var[1] = 536872045
Value of var[2] = 0
Address of var[2] = 536872046
Value of var[3] = 0
Address of var[3] = 536872047
Value of var[4] = 0
Address of var[4] = 536872048
Value of var[5] = 0
Address of var[5] = 536872049
Value of var[6] = 0
Address of var[6] = 536872050
Value of var[7] = 0
Address of var[7] = 536872051
Value of var[8] = 0
Address of var[8] = 536872052
Value of var[9] = 0
Address of var[9] = 536872053
Value of var[10] = 0
Address of var[10] = 536872054
Value of var[11] = 0
Address of var[11] = 536872055
Value of var[12] = 0
Address of var[12] = 536872056
Value of var[13] = 0
Address of var[13] = 536872057
Value of var[14] = 0
Address of var[14] = 536872058
Value of var[15] = 0
Address of var[15] = 536872059
Value of var[16] = 0
Address of var[16] = 536872060
Value of var[17] = 1811939328
Address of var[17] = 536872061
Value of var[18] = 74186752
Address of var[18] = 536872062
Value of var[19] = 289792
Address of var[19] = 536872063
Here var[17] is expected to be 0, but showing a different value. but if i print the var[17] value directly without pointer, am getting the correct result.
Upvotes: 1
Views: 108
Reputation: 961
In addition to what the other answers have said, you are accessing your arrays as if they are able to contain 20 elements, yet they are only 19 elements in length. D[19] declares an array of 19 elements, which should be accessed using D[0] through D[18], yet you are both writing and reading using 'i' which iterates from 0 through to 19, which will be both writing and reading past the ends of your arrays, causing further undefined behaviour.
Upvotes: 0
Reputation: 30926
You are violating strict aliasing rules.(S_data.D_ptr[i] = &S_data.D[i];
) So it is undefined behavior. You can't assign pointer of one type to another like this.
typedef struct
{
uint8_t D[19];
uint8_t *D_ptr[19];
} sys_data;
This solves the problem for you.
Also print uint32_t
using (if you declared it as uint32_t
).
printf("%" PRIu32 "\n", *S_data.D_ptr[i]);
Also print pointer like this
printf("%p", (void*)S_data.D_ptr[i]);
Upvotes: 2
Reputation: 12404
The part about UB was already explained in coderedoc's answer.
I want to add a few more details:
On some machines you will get an exception when you try to read a uint32
from an address that is not properly aligned. Odd addresses are good candidates for a bus error, a data fetch error or similar.
This is a consequence of violating strict aliasing rule.
If you access D_Ptr[16]
which points to D16
, you will access the memory from D[16]
to D[19]
which lies partially outside of sys_data
as var[19]
is out of bounds. Same for the other incorrect values.
You may read the location where your counter is stored, or something else that you don't show us.
Upvotes: 0