Changing a struct value within a function with c++ - struct

I wanted to create a quick quadtree in c++ but found that when I change a value of a struct within a function the value reverts. Also within the recursive function I wont some of the data created to be global. How do I do this?
#include <iostream>
struct a{
unsigned int value;
struct a * leaf[4];
};
void build(struct a root, unsigned int depth){
depth++;
root.value = 0;
struct a leaf0;
root.leaf[0] = &leaf0;
struct a leaf1;
root.leaf[1] = &leaf1;
struct a leaf2;
root.leaf[2] = &leaf2;
struct a leaf3;
root.leaf[3] = &leaf3;
if (depth != 5) {
build(*root.leaf[0], depth);
build(*root.leaf[1], depth);
build(*root.leaf[2], depth);
build(*root.leaf[3], depth);
}
}
int main(int argc, const char * argv[])
{
struct a root;
root.value = 364;
build(root, 0);
std::cout << root.value;
return 0;
}

You must pass the address of the struct to your function (which should accept a pointer to the struct):
void build(struct a *root, unsigned int depth) {
...
}
int main(int argc, const char * argv[])
...
build(&root, 0);
}

Related

change value of struct inside a struct

The secondexample below is what I would like to achieve in the firstcode written up. I want to ask how many 'dati' wants to insert then I have to do a malloc and I want to ask and save each dato of every struct so, firstly cdfM of the struct maestra and so on... How can I do that? How should I create the array with the malloc and how what should I do to save all the infos?
thx
#include <stdio.h>
#include <stdlib.h>
#define MAX 30
struct dati{
struct maestra{
char cdfM[MAX];
char nomeM[MAX];
char cognomeM[MAX];
char specializzazioneM[MAX];
}
struct classe{
int id;
char nome[MAX];
char colore[MAX];
}
struct insegnamento{
int idclasseI;
char cfmaestra[MAX];
}
struct bambino{
char cdfB[MAX];
char nomeB[MAX];
char cognomeB[MAX];
char dataNascita[MAX];
int idclasseB;
char dataIscrizione[MAX];
}
}
int main () {
struct dati *p,*q,*r,*s;
struct maestra **p;
struct classe **q;
struct insegnamento **r;
struct bambino **s;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define MAX 30
struct studente{
char nomeCognome[MAX];
int numeroMatricola;
float percentualeEP;
};
int main() {
struct studente *p;
int m, i;
printf("Quanti studenti devi inserire: \n");
scanf("%d", &m);
p = malloc(m*sizeof(int));
for (i=0; i < m; i++){
printf("Inserisci i dati dell'utente numero %d\n",i+1);
printf("Inserisci il nome cognome: \n");
scanf(" ");
fgets((p+i)->nomeCognome, MAX, stdin);
printf("Inserisci la matricola: \n");
scanf("%d",&(p+i)->numeroMatricola);
printf("Inserisci la percentuale di esami passati: \n");
scanf("%f", &(p+i)->percentualeEP);
}

How to compile intrinsic code in gcc

I am trying to compile this code:
#include <sys/types.h>
#include <argp.h>
#include <stdlib.h>
#include <xmmintrin.h>
__attribute__((noinline)) void vadd(float *a, float *b, size_t size)
{
size_t i;
for (i=0; i<size; i+=4)
{
__m128 v1 = _mm_load_ps(a + i); //loads up 4 floats into a __m128
__m128 v2 = _mm_load_ps(b + i); //loads up 4 floats into a __m128
__m128 v3 = _mm_add_ps(v1, v2);
_mm_store_ps(a+i, v3);
}
}
__attribute__((noinline)) void sadd(float *a, float *b, size_t size)
{
size_t i;
for(i=0; i<size; i++)
{
a[i] += b[i];
}
}
int main (void)
{
size_t size = 300000000;
float *a = (float *)calloc(size, sizeof(float));
float *b = (float *)calloc(size, sizeof(float));
vadd(a, b, size);
sadd(a, b, size);
}
I am receiving this error:
/usr/lib/gcc/i486-linux-gnu/4.8/include/mmintrin.h: In function ‘_mm_cvtsi32_si64’:
/usr/lib/gcc/i486-linux-gnu/4.8/include/mmintrin.h:61:3: error: can’t convert between vector values of different size
return (__m64) __builtin_ia32_vec_init_v2si (__i, 0);
Is there a way to work that out?

How to create thunk in x64?

I've found nice example how to create thunk for closure, but it's 32-bit version:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
struct env {
int x;
};
struct __attribute__((packed)) thunk {
unsigned char push;
struct env * env_addr;
unsigned char call;
signed long call_offset;
unsigned char add_esp[3];
unsigned char ret;
};
struct thunk default_thunk = {0x68, 0, 0xe8, 0, {0x83, 0xc4, 0x04}, 0xc3};
typedef void (* cfunc)();
struct thunk * make_thunk(struct env * env, void * code)
{
struct thunk * thunk = (struct thunk *)mmap(0,sizeof(struct thunk), PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
*thunk = default_thunk;
thunk->env_addr = env;
thunk->call_offset = code - (void *)&thunk->add_esp[0]; // Pretty!
mprotect(thunk,sizeof(struct thunk), PROT_EXEC);
return thunk;
}
void block(struct env * env) {
env->x += 1;
printf ("block: x is %d\n", env->x);
}
cfunc foo (int x)
{
struct env * env = (struct env *)malloc(sizeof(struct env));
env->x = x;
printf ("x is %d\n",env->x);
return (cfunc)make_thunk(env,(void *)&block);
}
int main() {
cfunc c = foo(5);
c();
c();
}
How can I rewrite it for 64-bit version?
I'm using Linux x86_64. I've been able to cross-compile it with gcc -m32, which worked perfectly.
The code below is designed to be used with GCC on Linux and should support 32 and 64 bit compilation.
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
struct env {
int x;
};
#if __x86_64__
struct __attribute__((packed)) thunk {
unsigned char mov[2];
struct env * env_addr;
unsigned char movrax[2];
void (*call_address)();
unsigned char jmp[2];
};
struct thunk default_thunk = {{0x48, 0xbf}, 0x0, {0x48, 0xb8}, 0x0, {0xff, 0xe0} };
#elif __i386__
struct __attribute__((packed)) thunk {
unsigned char push;
struct env * env_addr;
unsigned char call;
signed long call_offset;
unsigned char add_esp[3];
unsigned char ret;
};
struct thunk default_thunk = {0x68, 0, 0xe8, 0, {0x83, 0xc4, 0x04}, 0xc3};
#else
#error Architecture unsupported
#endif
typedef void (* cfunc)();
struct thunk * make_thunk(struct env * env, void * code)
{
struct thunk * thunk = (struct thunk *)mmap(0,sizeof(struct thunk),
PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
*thunk = default_thunk;
#if __x86_64__
thunk->env_addr = env;
thunk->call_address = code; /* Pretty! */
#else
thunk->env_addr = env;
thunk->call_offset = code - (void *)&thunk->add_esp[0]; /* Pretty! */
#endif
mprotect(thunk,sizeof(struct thunk), PROT_EXEC);
return thunk;
}
void block(struct env * env) {
env->x += 1;
printf ("block: x is %d\n", env->x);
}
cfunc foo (int x)
{
struct env * env = (struct env *)malloc(sizeof(struct env));
env->x = x;
printf ("x is %d\n",env->x);
return (cfunc)make_thunk(env,(void *)&block);
}
int main() {
cfunc c = foo(5);
c();
c();
return 0;
}
Assuming that the OS is using System V 64bit ABI (Which Linux uses) calling convention then the first parameter that will be passed to the function will be in register %rdi. Then we just have to mov the environment address (env_addr) to %rdi and then do a call. The call uses an indirect jump to an absolute location through %rax. So the instruction sequence looks like (at&t syntax):
mov $env_addr, %rdi
movabs $call_pointer, %rax
jmpq *%rax # Tail call instead of call/retq

Global initialization of structure

How can I initialize struct sockaddr_in globally. Third variable IN_ADDR sin_addr is a nested structure.
struct sockaddr_in{
short sin_family;
unsigned short sin_port;
IN_ADDR sin_addr;
char sin_zero[8];
} addr;
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
};
Point 1
You cannot initalize struct sockaddr_in itself. You need to have a variable of this type, i.e, addr (as in your case) which you can initialize.
Point 2
You can use an inilitalizer list in brace-enclosed form to initialize the global variable. Also, you can make use of the .identifier option to initalize a member explicitly.
Assuming IN_ADDR is defined as
typedef struct sockaddr_in IN_ADDR;
you can write something like
struct sockaddr_in{
short sin_family;
unsigned short sin_port;
IN_ADDR sin_addr;
char sin_zero[8];
} addr = {AF_INET, 2015, .sin_addr.S_un.S_addr = 1234567890, .sin_zero = {1,2,3,4,5,6,7}};
to initilialize addr.
Here, the .sin_addr.S_un.S_addr is used to denote to the particular variable to be initializeed.
Using your structure/union definition ... here is a sample program ...
#include <stdio.h>
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
typedef struct in_addr
{
union
{
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
}S_un;
}IN_ADDR;
IN_ADDR u = // ====> Either do something like this ...
{
.S_un.S_un_b = {'a', 'b', 'c', 'd'}
//.S_un.S_un_w = {1, 2},
//.S_un.S_addr = 121212
};
struct sockaddr_in
{
short sin_family;
unsigned short sin_port;
IN_ADDR sin_addr;
char sin_zero[8];
}addr = { // ==============> Or do something like this.
10,
20,
.sin_addr.S_un.S_addr=12345,
"SOCKET"
};
int main()
{
printf("sin_family = %d\n", addr.sin_family);
printf("sin_port = %d\n", addr.sin_port);
printf("sin_addr.S_un.S_addr = %ld\n", addr.sin_addr.S_un.S_addr);
printf("sin_zero = %s\n", addr.sin_zero);
printf("%c %c %c %c\n", u.S_un.S_un_b.s_b1, u.S_un.S_un_b.s_b2, u.S_un.S_un_b.s_b3, u.S_un.S_un_b.s_b4);
//printf("%d %d\n", u.S_un.S_un_w.s_w1, u.S_un.S_un_w.s_w2);
//printf("%ld\n", u.S_un.S_addr);
return 0;
}

Interfacing with structs and anonymous unions with c2hs

How would one go about encoding this chunk of C code in a .chs file so that c2hs can transform it to something relatively nice?
typedef enum {
MONOME_BUTTON_UP = 0x00,
MONOME_BUTTON_DOWN = 0x01,
MONOME_ENCODER_DELTA = 0x02,
MONOME_ENCODER_KEY_UP = 0x03,
MONOME_ENCODER_KEY_DOWN = 0x04,
MONOME_TILT = 0x05,
/* update this if you add event types */
MONOME_EVENT_MAX = 0x06
} monome_event_type_t;
typedef struct monome monome_t; /* opaque data type */
typedef struct monome_event monome_event_t;
typedef void (*monome_event_callback_t)
(const monome_event_t *event, void *data);
struct monome_event {
monome_t *monome;
monome_event_type_t event_type;
/* __extension__ for anonymous unions in gcc */
__extension__ union {
struct {
unsigned int x;
unsigned int y;
} grid;
struct {
unsigned int number;
int delta;
} encoder;
struct {
unsigned int sensor;
int x;
int y;
int z;
} tilt;
};
};
How about this: change the code so that you name the members. The layout in memory is the same so that it will be binary compatible. You would have to do this patch for each version of the lib.
struct monome_event {
monome_t *monome;
monome_event_type_t event_type;
/* __extension__ for anonymous unions in gcc */
__extension__ union {
struct me_grid {
unsigned int x;
unsigned int y;
} grid;
struct me_encoder {
unsigned int number;
int delta;
} encoder;
struct me_tilt {
unsigned int sensor;
int x;
int y;
int z;
} tilt;
};
};

Resources