Array of structure pointer in C - c

I am running following code.
#include <stdio.h>
struct point
{
int formatbyte1;
int formatbyte2;
int formatbyte3;
};
const struct point SW_VERSN_POINT =
{
1,2,3
};
const struct point SWMVERSN_POINT =
{
4,5,6
};
const struct point *object_directory[] =
{
&SW_VERSN_POINT,
&SWMVERSN_POINT,
0
};
int main()
{
printf("%ld\n", sizeof(SW_VERSN_POINT.formatbyte1));
printf("%ld 0X%X, 0x%X\n", sizeof(struct point), &SWMVERSN_POINT.formatbyte1, &SW_VERSN_POINT.formatbyte1);
printf("%ld 0X%X, 0x%X\n", sizeof(object_directory), object_directory[0], object_directory[1]);
return 0;
}
The output of above program is
4
12 0XE2BF0788, 0xE2BF0778
24 0XE2BF0778, 0xE2BF0788
But when I modified the object_directory, removed 0 from it
const struct point *object_directory[] =
{
&SW_VERSN_POINT,
&SWMVERSN_POINT
};
Now output of above program is
4
12 0XF967D788, 0xF967D778
16 0XF967D778, 0xF967D788
Why is the size of object_directory is changes from 24 to 16. (How does 16 come from)
Thanks in advance.
This code is running on Linux.

Related

C mutating struct properties by reference

I'm learning pointers in C and i came across a confusion between pointers X struts X functions
The goal: creating two structs and mutate properties inside them.
The path I'm going: I am creating these two structs and then passing its memory addresses to the mutate function, the function then prints and mutates some properties of these structs.
Result I get:
1: The name of the struct created is nod being entirely printed and its of the wrong struct passed, and the life property is not properly changed and printed to the screen.
2: On the terminal I get "Segmentation Fault", not sure why but I'm pretty sure its something wrong I did.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int power;
int life;
char name[];
} Hero;
void attackHero(Hero *hero, int *power) {
(*hero).life = (*hero).life - *power;
printf("Damage: %d\n", *power);
printf("Attacked hero: %s\n", (*hero).name);
printf("Hero's remaining life: %d\n", (*hero).life);
};
int main () {
Hero flash;
flash.power = 250;
flash.life = 500;
strcpy(flash.name, "The Flash");
Hero batman;
batman.power = 380;
batman.life = 700;
strcpy(batman.name, "Batman arkham knight");
attackHero(&flash, &batman.power);
return 0;
}
Result printed to the terminal (Vscode + gcc):
Here is the warning that I get when I compile your original code:
1.c:25:2: warning: ‘__builtin_memcpy’ writing 10 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
25 | strcpy(flash.name, "The Flash");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.c:30:2: warning: ‘__builtin_memcpy’ writing 21 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
30 | strcpy(batman.name, "Batman arkham knight");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to use the flexible array then you have to allocate space for it like this:
int main () {
Hero *flash = malloc(sizeof(*flash) + sizeof("The Flash"));
flash->power = 250;
flash->life = 500;
strcpy(flash->name, "The Flash");
Hero *batman = malloc(sizeof(*flash) + sizeof("Batman arkham knight"));
batman->power = 380;
batman->life = 700;
strcpy(batman->name, "Batman arkham knight");
attackHero(flash, &batman->power);
free(flash);
free(batman);
}
Here there the resulting code refactored a bit, and I added a error check for malloc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int power;
int life;
char name[];
} Hero;
Hero *createHero(int power, int life, const char *name) {
Hero *h = malloc(sizeof(*h) + strlen(name) + 1);
if(!h) {
printf("malloc failed\n");
exit(1);
}
h->power = power;
h->life = life;
strcpy(h->name, name);
return h;
}
void attackHero(Hero *hero, int power) {
hero->life -= power;
printf(
"Damage: %d\n"
"Attacked hero: %s\n"
"Hero's remaining life: %d\n",
power,
hero->name,
hero->life
);
};
int main(void) {
Hero *flash = createHero(250, 500, "The Flash");
Hero *batman = createHero(380, 700, "Batman arkham knight");
attackHero(flash, batman->power);
free(flash);
free(batman);
}
Alternatively use a fixed array (char [64] as suggested by #Diego) or a char * and allocate space to it. The former only needs 2 lines of code change from the original:
// largest name in use
#define NAME_LEN sizeof("Batman arkham knight")
typedef struct {
int power;
int life;
char name[NAME_LEN];
} Hero;
Whole lotta malloc() going on. Since the hero’s names are string literals (and assuming they don’t change), just change name[]; to const char *name in the structure and initialize via simple assignment:
flash.name = "The Flash";
batman.name = "Batman arkham knight";
No worries about malloc() failures, name sizes or free() requirements.

Initialize a flexible array of arrays in a struct

The title corresponds to my last attempt, I try to store color values ​​corresponding to walls, a bit like this:
#include <stdint.h>
typedef uint8_t RGB[3];
typedef RGB ColorArray[];
typedef struct {
int wall_num;
ColorArray wall_colors;
} Map;
int main(void)
{
int wall_num = 3;
ColorArray wall_colors = {
*(RGB){ 255, 0, 0 },
*(RGB){ 0, 255, 0 },
*(RGB){ 0, 0, 255 }
};
Map my_map = {wall_num, wall_colors}; // error: non-static initialization of a flexible array member
return 0;
}
But I get this:
error: non-static initialization of a flexible array member
I tried other ways with pointers but I quickly realized that it was pointing to anything and so I got any colors until a segfault...
Is there a way to do it like this ? Or is it just the wrong way to go and I have to start all over again ?
UPDATE - (SELF ANSWER):
So I decided to call malloc() because no alternative was satisfactory for my case, I share what I did if it can help someone:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef uint8_t RGB[3];
typedef RGB RGB_Array[];
typedef struct {
int wall_num;
RGB_Array wall_colors;
} Map;
void print_map (Map *m) {
printf("wall_num: %d\n", m->wall_num);
for (int i = 0; i < m->wall_num; ++i) {
printf("wall_colors[%d]: (R:%d, G:%d, B:%d)\n", i,
m->wall_colors[i][0],
m->wall_colors[i][1],
m->wall_colors[i][2]);
}
}
int main(void)
{
int wall_num = 3;
RGB_Array color_arr = {
{255,0,0},
{0,255,0},
{0,0,255}
};
Map* map = malloc(sizeof(Map) + sizeof(color_arr));
map->wall_num = wall_num;
memcpy(map->wall_colors, color_arr, sizeof(color_arr));
print_map(map);
free(map); // free is for example
return 0;
}
Otherwise, jxh's answer is still interesting and perfectly does what was asked for, even if it doesn't suit me personally, I validate it anyway.
You cannot use an array name to initialize an array variable anyway.
There is no memory associated with the flexible array member. It is a convenience to allow you to have a name for the end of the struct to refer to the array that you intend to allocate behind the struct.
Typically, you would use malloc() and add the size of the array to the size of the struct to get a single object to represent your structure with the flexible array.
However, you can do it off the "stack" by defining a new structure where the flexible array member is replaced with an array of the appropriate size, and then casting a pointer to this structure to your desired type.
Alternatively, you could use a union and avoid the casting.
Both techniques are illustrated below. First some helpers:
...
#define MAP_TEMPLATE(N) struct { \
int wall_num; \
RGB wall_colors[N]; \
}
...
void print_map (Map *m) {
printf("wall_num: %d\n", m->wall_num);
for (int i = 0; i < m->wall_num; ++i) {
printf("wall_colors[%d]: (R:%d, G:%d, B:%d)\n", i,
m->wall_colors[i][0],
m->wall_colors[i][1],
m->wall_colors[i][2]);
}
}
Then using a new structure:
MAP_TEMPLATE(3) my_map1 = {
wall_num,
{ { 155, 0, 0 },
{ 0, 155, 0 },
{ 0, 0, 155 },
},
};
print_map((Map *)&my_map1);
And using a union:
union {
MAP_TEMPLATE(3) _;
MAP_TEMPLATE();
} my_map2 = {
{ wall_num,
{ { 255, 0, 0 },
{ 0, 255, 0 },
{ 0, 0, 255 },
},
},
};
print_map((Map *)&my_map2);

How to use the ARM PMU in GEM5?

I had a problem initializing the PMU in gem5 for an arm full system with the starter_fs.py in --cpu hpi.
i followed the instructions of this post Using perf_event with the ARM PMU inside gem5 and i managed to solve my problem. I added the patch and configure the system. I am not using perf. I try to access directly the registers and read them. As i see GEM5 has only some register events implemented. Can we add the others as well as :
for example EXC_TAKEN is not implemented. Is the following the way to add them?
self.addEvent(ProbeEvent(self,0x09, cpu, "EXC_TAKEN"))
#0x09: EXC_TAKEN ???
Also, reading the pmu event registers i manage to read them and extract the events but the pmccntr cycle register always returns zero? How gem5 increments this register? What are the steps to read the cycle reggister?
a code that i use to read using perf is the following:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/perf_event.h>
#define NUM_NODES 100
#define NONE 9999
struct _NODE
{
int iDist;
int iPrev;
};
typedef struct _NODE NODE;
struct _QITEM
{
int iNode;
int iDist;
int iPrev;
struct _QITEM *qNext;
};
typedef struct _QITEM QITEM;
QITEM *qHead = NULL;
int AdjMatrix[NUM_NODES][NUM_NODES];
int g_qCount = 0;
NODE rgnNodes[NUM_NODES];
int ch;
int iPrev, iNode;
int i, iCost, iDist;
void print_path (NODE *rgnNodes, int chNode)
{
if (rgnNodes[chNode].iPrev != NONE)
{
//print_path(rgnNodes, rgnNodes[chNode].iPrev);
}
//printf (" %d", chNode);
fflush(stdout);
}
void enqueue (int iNode, int iDist, int iPrev)
{
QITEM *qNew = (QITEM *) malloc(sizeof(QITEM));
QITEM *qLast = qHead;
if (!qNew)
{
//fprintf(stderr, "Out of memory.\n");
exit(1);
}
qNew->iNode = iNode;
qNew->iDist = iDist;
qNew->iPrev = iPrev;
qNew->qNext = NULL;
if (!qLast)
{
qHead = qNew;
}
else
{
while (qLast->qNext) qLast = qLast->qNext;
qLast->qNext = qNew;
}
g_qCount++;
// ASSERT(g_qCount);
}
void dequeue (int *piNode, int *piDist, int *piPrev)
{
QITEM *qKill = qHead;
if (qHead)
{
// ASSERT(g_qCount);
*piNode = qHead->iNode;
*piDist = qHead->iDist;
*piPrev = qHead->iPrev;
qHead = qHead->qNext;
free(qKill);
g_qCount--;
}
}
int qcount (void)
{
return(g_qCount);
}
int dijkstra(int chStart, int chEnd)
{
for (ch = 0; ch < NUM_NODES; ch++)
{
rgnNodes[ch].iDist = NONE;
rgnNodes[ch].iPrev = NONE;
}
if (chStart == chEnd)
{
//printf("Shortest path is 0 in cost. Just stay where you are.\n");
}
else
{
rgnNodes[chStart].iDist = 0;
rgnNodes[chStart].iPrev = NONE;
enqueue (chStart, 0, NONE);
while (qcount() > 0)
{
dequeue (&iNode, &iDist, &iPrev);
for (i = 0; i < NUM_NODES; i++)
{
if ((iCost = AdjMatrix[iNode][i]) != NONE)
{
if ((NONE == rgnNodes[i].iDist) ||
(rgnNodes[i].iDist > (iCost + iDist)))
{
rgnNodes[i].iDist = iDist + iCost;
rgnNodes[i].iPrev = iNode;
enqueue (i, iDist + iCost, iNode);
}
}
}
}
//printf("Shortest path is %d in cost. ", rgnNodes[chEnd].iDist);
//printf("Path is: ");
//print_path(rgnNodes, chEnd);
//printf("\n");
}
}
int main(int argc, char *argv[]) {
int diff = 0;
uint64_t num_cycles_nominal=0;
uint64_t num_cycles_attack=0;
uint64_t counter_cpu_cycles = 0;
//system("./load-module");
int i,j,k;
FILE *fp;
static int perf_fd_cpu_cycles;
static struct perf_event_attr attr_cpu_cycles;
attr_cpu_cycles.size = sizeof(attr_cpu_cycles);
attr_cpu_cycles.exclude_kernel = 1;
attr_cpu_cycles.exclude_hv = 1;
attr_cpu_cycles.exclude_callchain_kernel = 1;
attr_cpu_cycles.type = PERF_TYPE_RAW;
attr_cpu_cycles.config = 0x11;
/* Open the file descriptor corresponding to this counter. The counter
should start at this moment. */
if ((perf_fd_cpu_cycles = syscall(__NR_perf_event_open, &attr_cpu_cycles, 0, -1, -1, 0)) == -1)
fprintf(stderr, "perf_event_open fail %d %d: %s\n", perf_fd_cpu_cycles, errno, strerror(errno));
if (argc<2) {
//fprintf(stderr, "Usage: dijkstra <filename>\n");
//fprintf(stderr, "Only supports matrix size is #define'd.\n");
}
/* open the adjacency matrix file */
fp = fopen (argv[1],"r");
/* make a fully connected matrix */
for (i=0;i<NUM_NODES;i++) {
for (j=0;j<NUM_NODES;j++) {
/* make it more sparce */
fscanf(fp,"%d",&k);
AdjMatrix[i][j]= k;
}
}
/* Get and close the performance counters. */
read(perf_fd_cpu_cycles, &counter_cpu_cycles, sizeof(counter_cpu_cycles));
//close(perf_fd_cpu_cycles);
printf("Number of cpu_cycles before: %d\n", counter_cpu_cycles);
num_cycles_nominal = counter_cpu_cycles;
/* Get and close the performance counters. */
read(perf_fd_cpu_cycles, &counter_cpu_cycles, sizeof(counter_cpu_cycles));
//close(perf_fd_cpu_cycles);
printf("Number of cpu_cycles after attack: %d\n", counter_cpu_cycles);
num_cycles_attack = counter_cpu_cycles - num_cycles_nominal;
/* finds 10 shortest paths between nodes */
for (i=0,j=NUM_NODES/2;i<100;i++,j++) {
j=j%NUM_NODES;
dijkstra(i,j);
}
read(perf_fd_cpu_cycles, &counter_cpu_cycles, sizeof(counter_cpu_cycles));
close(perf_fd_cpu_cycles);
printf("Number of cpu_cycles end: %d\n", counter_cpu_cycles);
num_cycles_nominal = counter_cpu_cycles - num_cycles_attack;
printf("Number of cpu_cycles nominal: %d\n", num_cycles_nominal);
printf("Number of cpu_cycles attack: %d\n", num_cycles_attack);
exit(0);
}
the problem is that i can read the branch misses with perf having 0x10 instead 0f 0x11 (cycle counters RAW EVENT in GEM5) but using 0x11 for reading the cycles i get zero. When i try to reverse engineer the increment of cycle counter i do the following comments:
when simple/atomic or simple/timing i see that updateCycleCounter is called from the base.hh, also for the 03 cpu model. When HPI and considering that hpi is a MinorCPU model i see that updateCycleCounter is called only in POWER_STATE_ON, but i didnt find in the code a POWER_STATE_ON reference updateCycleCounter(CPU_STATE_ON) which will update the cycle counter. Please help me verify this assumption.
*****The problem was that in the MinorCPU the updateCycleCounter wasnt called for the CPU_STATE_ON which updates the ActiveCycles. It was fixed by the following patch https://gem5-review.googlesource.com/c/public/gem5/+/38095 .

Pointer to array of pointers points to unexpected address

The question is related to my former question here:
Arduino compile error while using reference to a struct in another struct
I ported the sample code back to the pc and compiled it to get a clue, what's going wrong.
Here's the sample:
#include <stdio.h>
unsigned int steps=64;
unsigned int mode=0;
unsigned int speed=1;
typedef struct{
unsigned int option_value;
char option_name[17];
} SELECTION;
typedef struct{
char item_name[17];
unsigned int* variable;
SELECTION** options;
} MENU_ITEM;
SELECTION mode_forward = { 0, "Forward" };
SELECTION mode_backward = { 1, "Backward" };
SELECTION* options_mode[] = { &mode_forward, &mode_backward };
SELECTION speed_slow = { 0, "Slow" };
SELECTION speed_normal = { 1, "Normal" };
SELECTION speed_fast = { 2, "Fast" };
SELECTION* options_speed[] = { &speed_slow, &speed_normal, &speed_fast };
MENU_ITEM menu_steps = { "Steps", &steps, NULL };
MENU_ITEM menu_mode = { "Mode", &mode, options_mode };
MENU_ITEM menu_speed = { "Speed", &speed, options_speed };
MENU_ITEM menu_exit = { "Exit", NULL, NULL };
const unsigned char menu_items = 4;
MENU_ITEM* menu_list[menu_items] = { &menu_steps, &menu_mode, &menu_speed, &menu_exit };
//-----------------------------------------------------------
int main(){
int options;
options=(int)(sizeof(options_speed)/sizeof(options_speed[0]));
printf("Speed options: %i\n\n",options);
printf("Address of speed_slow: %p\n",&speed_slow);
printf("Address of speed_normal: %p\n",&speed_normal);
printf("Address of speed_fast: %p\n",&speed_fast);
printf("Address of array: %p\n\n",&options_speed);
MENU_ITEM item;
item=*menu_list[2];
printf("Menu Item: %s - Item Value: %i\n",item.item_name,*item.variable);
printf("Address of name: %p\n",&item.item_name);
printf("Address of variable-pointer: %p\n",&item.variable);
printf("Address of options-pointer: %p\n",&item.options);
printf("Value of options-pointer: %p\n",*item.options);
return 0;
}
When i start the program i get the following output:
Speed options: 3
Address of speed_slow: 0x6010c0
Address of speed_normal: 0x6010e0
Address of speed_fast: 0x601100
Address of array: 0x601120
Menu Item: Speed - Item Value: 1
Address of name: 0x7fff18a5dc90
Address of variable-pointer: 0x7fff18a5dca8
Address of options-pointer: 0x7fff18a5dcb0
Value of options-pointer: 0x6010c0
That's what i expect....except the last line. Shouldn't the address that it points to be 0x601120 - the address of options_speed array?
Why does it point to the first member of the array instead?
What do i have to change to let it point to 0x601120?
You are evaluating *item.options, not item.options. This seems is not what you wanted to print (i.e. the "options pointer") as there is an extra dereferencing operation.

iterate through null terminated array

I want to iterate through null terminated structure array.
While loop works fine, but when I try to access any structure fields I get "segfault" in response. What am I doing wrong?
PS I know that it is possible to determine array size and use simple "for" construction. I just want to figure out the source of the problem.
PSS Ok, if array initialization is wrong - how to do it correctly?
#include <stdio.h>
#include <stdlib.h>
typedef struct demo
{
int a;
int b;
int c;
} demo;
demo * fieldDefinitions[] =
{
{ 1 , 1, 1 },
{ 2 , 2, 2 },
{ 3 , 3, 3 },
NULL
};
int main()
{
demo ** ptr = fieldDefinitions;
printf( "Array: %d \n", &fieldDefinitions );
while ( *ptr != NULL )
{
printf( "ptr: %d \n", ptr );
printf( "ptr: %d \n", (**ptr).a ); // <--- problem here
ptr++;
}
return 0;
}
As the others already've pointed out: Listen to your compiler, a standard conforming implementation must complain about:
demo * fieldDefinitions[] =
{
{ 1 , 1, 1 }, // <-- note that this is not a pointer to a demo.
{ 2 , 2, 2 },
{ 3 , 3, 3 },
NULL
};
Also, use p as the printf format specifier for pointers, not d (which is for integer types).
You need pointers to demo objects, so these objects need to be created somehow, so that we can take their addresses. C99 added a feature called compound literals (looking somewhat similar to a cast, however, they are something different) creating unnamed objects:
#include <stdio.h>
#include <stdlib.h>
typedef struct demo
{
int a;
int b;
int c;
} demo;
demo * fieldDefinitions[] =
{
&(demo){ 1 , 1, 1 },
&(demo){ 2 , 2, 2 },
&(demo){ 3 , 3, 3 },
NULL
};
int main()
{
demo ** ptr = fieldDefinitions;
printf( "Array: %p \n", (void *)&fieldDefinitions );
for ( ; *ptr != NULL; ptr++ )
{
printf( "ptr: %p\n", (void *)ptr); // I'm not sure, what you really wanted ...
printf( "*ptr: %p\n", (void *)*ptr ); // ... but I think you meant this
printf( "ptr: %d\n", (*ptr)->a ); // or (**ptr).a, whatever you prefer
}
return 0;
}
The lifetime of an object created via a compound literal is that of the enclosing block or static if used in an initializer for an identifier with static storage duration (as in this example).
HTH
demo * fieldDefinitions[ 4 ] =
{
{ 1 , 1, 1 },
{ 2 , 2, 2 },
{ 3 , 3, 3 },
NULL
};
You can't do that, as you can not do:
int *arr[] = {1, 2, 3, NULL};
Turning your warnings on you get:
initialization makes pointer from integer without a cast
If you want to use pointer arithmetic you can do somenting like:
#include <stdio.h>
#include <stdlib.h>
typedef struct demo
{
int a;
int b;
int c;
} demo;
demo fieldDefinitions[] = {
{ 1 , 1, 1 },
{ 2 , 2, 2 },
{ 3 , 3, 3 },
};
int main(void)
{
demo *ptr = fieldDefinitions;
demo *end = &fieldDefinitions[sizeof(fieldDefinitions) / sizeof(fieldDefinitions[0]) - 1];
do {
printf( "ptr: %p \n", (void *)ptr);
printf( "ptr: %d \n", ptr->a);
} while (ptr++ < end);
return 0;
}
demo * fieldDefinitions[] =
{
{ 1 , 1, 1 },
{ 2 , 2, 2 },
{ 3 , 3, 3 },
NULL
};
you are claiming that fieldDefinitions will be an array of demo object pointers, but instead you are giving objects themselves.This is the way you initialize an array of structures (except NULL at the end). If your array is static then i suggest creating array of demo with known size such as
unsigned const int fieldDefinitions_size = 3;
demo fieldDefinitions_arr[fieldDefinitions_size] = {
{1,1,1},
{2,2,2},
{3,3,3}
};
And iterate by using fieldDefinitions_size.
Or if you insist on having demo pointer array then you can individually allocate memory for each demo object and assign addresses to fieldDefinitions array. This thread will be useful.

Resources