How to access nested structure using pointer and array? - c

typedef struct
{
unsigned int a;
unsigned char b[10];
unsigned char c;
}acc1;
typedef struct
{
unsigned char z[10];
acc1 *x,y[10];
}acc2;
extern acc2 p[2];
I want to access struct acc1 variables from acc2 array p[2].
I'm getting segmenatation faults when I do it. Please guide on how to do this

To access y's elements do:
char c = p[some index between 0 and 1].y[some index between 0 and 9].c
To access elements referred to by x do:
size_t i = some index between 0 and 1;
p[i].x = malloc(somenumber_of_elements * sizeof *p[i].x);
if (NULL == p[i].x)
{
abort(); /* Failure to allocate memory. */
}
char c = p[i].x[some index less then somenumber_of_elements].c;
Referring kabhis comment
p[0].x->c is it not correct ?
Assuming the allocation above with somenumber_of_elements greater 0, then:
char c = p[i].x[0].c;
is equivalent to
char c = p[i].x->c;
and for somenumber_of_elements greater 1
char c = p[i].x[1].c;
is equivalent to
char c = (p[i].x + 1)->c;
and so on ...

Related

How to assign value to multiple member a structure at once

Let's assume that we have a struct that has 4x 1-byte members.
I want to use Xyz as a memory address and cast it as a 32bit pointer then I will assign values to it.
By this, I would able to set all the byte members at once.
This is just an example for my question, char, int, or set to 256 is just arbitrary examples.
#include <stdio.h>
struct temp{
char abc;
char def;
char ghk;
char lmn;
}xyz;
int main()
{
xyz = (struct temp){11,22,33,44};
printf("Byte1 %d\r\n",xyz.abc);
printf("Byte2 %d\r\n",xyz.def);
printf("Byte3 %d\r\n",xyz.ghk);
printf("Byte4 %d\r\n",xyz.lmn);
*((unsigned int*)xyz) = 256;
printf("Byte1 %d\r\n",xyz.abc);
printf("Byte2 %d\r\n",xyz.def);
printf("Byte3 %d\r\n",xyz.ghk);
printf("Byte4 %d\r\n",xyz.lmn);
return 0;
}
Here I prepare a similar approach for the array which is working as expected ;
#include <stdio.h>
char mem[4];
int main()
{
mem[0] = 49;
mem[1] = 50;
mem[2] = 51;
mem[3] = 52;
printf("Byte1 %d\r\n",mem[0]);
printf("Byte2 %d\r\n",mem[1]);
printf("Byte3 %d\r\n",mem[2]);
printf("Byte4 %d\r\n",mem[3]);
*(int*)mem = 256;
printf("Byte1 %d\r\n",mem[0]);
printf("Byte2 %d\r\n",mem[1]);
printf("Byte3 %d\r\n",mem[2]);
printf("Byte4 %d\r\n",mem[3]);
return 0;
}
How can I do the same thing that I did by an array by using struct?
This:
*((unsigned int*)xyz) = 256;
Is a strict aliasing violation. This means you can't take a pointer to one type, cast it to another type, dereference the casted pointer, and expect things to work. The only exception is casting to a pointer to char * to read the individual bytes of some other type.
What you can do however is use a union. It is permitted to write to one member of a union and read from another to reinterpret the bytes as a different type. For example:
union u {
int i;
struct {
char c1;
char c2;
char c3;
char c4;
} s;
};
...
union u u1;
u1.i = 256;
printf("byte1=%02x\n", u1.c1);
printf("byte2=%02x\n", u1.c2);
printf("byte3=%02x\n", u1.c3);
printf("byte4=%02x\n", u1.c4);

Passing a element of a char array into another position

So i have a struct with the following elements:
typedef struct loja{
int numero;
char nome[MAX];
float area;
float faturacao[12];
} Loja[N];
i declared an array vetC[ ] for the struct and my next step was to eliminate a posicion of that array
int EliminarComum(int c,Loja vetC[]){
int posicao, i,a;
posicao = MostrarComum(c,vetC); ///only for the user to choose the position he wishes to eliminate.
if (posicao > c)
printf("can't delete.\n");
else {
for (i = posicao - 1; i < c - 1; i++){
vetC[i]->numero = vetC[i+1]->numero;
vetC[i]->nome = vetC[i+1]->nome;
vetC[i]->area = vetC[i+1]->area;
for(a=0;a<12;a++)
vetC[i]->faturacao[a] = vetC[i+1]->faturacao[a];
c--;
}
}
return c;
}
and in the line of vetC[i]->nome = vetC[i+1]->nome; gives me the error
error: assignment to expression with array type
You cannot assign arrays, but you could assign complete struct loja-objects:
vetC[i] = vetC[i+1];
Conver, for example, the following simple program, which illustrates how an assignment of struct-objects works, while an assignment of a char-array fails:
struct testStruct {
int x;
char str[10];
};
int main() {
struct testStruct t1 = { 10, "Hello" };
struct testStruct t2;
t2 = t1; // legal.
char str1[10] = "Hello";
char str2[10];
// str2 = str1; // illegal; arrays cannot be assigned.
strcpy(str2,str1); // legal (as long as str1 is a valid string)
}

how to malloc for this structure

typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char *macsStrList[MAC_ADDR_STR_LEN];
} testMsg_t;
Number of elements in macsStrList is m_Count.
I know following is not correct:
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
This is correct, given the structure you have done
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
However you are probably confused to the meaning of *arr[dimension] -- which is an array length dimension of pointers to chars -- reading between the lines,
MAC_ADDR_STR_LEN
Is probably ment to the legth of the string representation of a mac address (say <20 bytes?)
However your struct gives you 20 char pointers, and the character pointers still have to be initializaed to point to valid memory.
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
pInput->macsStrList[0] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[1] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[2] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
...
or redefine your struct to
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[NUMBER_OF_MAC_ADDRESSES][MAC_ADDR_STR_LEN];
} testMsg_t;
To avoid having to deal with multiple number of allocations.
ADDITION;
As per comments, given that the number of mac addresses are dynamically determined, you could also define the struct as;
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[1][MAC_ADDR_STR_LEN];
} testMsg_t;
and then allocate it using
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) + (countOfMacsAddresses * MAC_ADDR_STR_LEN) );
That would have the added over a solution with pointers of that you could use realloc to resize the array dynamically if you needed to do that as well.....
I think what you're looking for is maybe (ok, Soren got in first, but I'll show a way to allocate a single contiguous chunk):
/* assuming we only need macStrList[0] ... [Count-1] */
struct testMsg
{
unsigned char opCode;
unsigned int Count;
char *macsStrList[];
};
struct testMsg *allocate_testMsg(int count)
{
char *string_storage;
struct testMsg *msg;
size_t size = sizeof(struct testMsg) /* base object */
+ (count * sizeof(char *)) /* char* array */
+ (count * (MAC_ADDR_STR_LEN+1)) /* char storage */
;
msg = malloc(size);
msg->Count = count;
string_storage = (char *)&(msg->macStrList[count]);
/* note msg->macStrList points to UNINITIALIZED but allocated storage.
it might be sensible to zero-fill string_storage, depending on how you'll
initialize it
*/
for (count=0; count < msg->Count;
++count, string_storage += (MAC_ADDR_STR_LEN+1))
{
msg->macStrList[count] = string_storage;
}
return msg;
}
Of course it is. You allocate a pointer to a testMsg_t which is an alias for struct testMsg_. However you need to initialize this object yourself.
(And you don't need to cast the allocated pointer in C).

Storing the 2 arrays in a datastructure

I have 2 language codes coming in the stream. I'm storing this in a 3 byte char array(unsigned char a[3]). I wanted to compare it with another value stored in a pointer(unsigned char *c).The array a[3] is stored inside a structure(struct s[2]) to get the multiple datas - Is this correct as i'm little confused as array - const pointer cannot be made to point to another location as it is already pointing to a location. But including the array inside a structure and making the zeorth element of the structures array to point to one location and the 1 st element of the structures array is possible. Is the understanding i have is correct.
I wanted to store the 2 array values.So I have declared a structure inside which i have declared the 3 byte char array.Is this way of doing is correct. Is there alternate way to do it.
EDITED:
#include<stdio.h>
int main(){
int i,flag=0,count=0;
struct n{
unsigned char b[3];
};
unsigned char *d=NULL;
struct s{
unsigned char *a;
};
struct s m[2];
struct n w[2];
// memcpy(w[0].b,"eng",sizeof("eng"));
// memcpy(w[1].b,"fre",sizeof("fre"));
strcpy(w[0].b,"eng");
strcpy(w[1].b,"fre");
d = w[1].b; // current lang
m[0].a = w[0].b; // storing the 2 lang in a pointer inside a structure
m[1].a = w[1].b;
i=0;
printf("\nm[0].a:%s\n",m[0].a);
printf("\nm[1].a:%s\n",m[1].a);
printf("\nw[0].b:%s\n",w[0].b);
printf("\nw[1].b:%s\n",w[1].b);
while((m[i].a) && d){ // And comparing
if(m[i].a++ != d++){
flag =1; //if strings are unequal break;
break;
}
i++;
}
if(flag){
printf("Not equal\n");
}
else{
printf("\nEqual\n");
flag =0;
}
return 0;
}
o/p:
m[0].a:engfre
m[1].a:fre
w[0].b:engfre
w[1].b:fre
Not equal
But there s an mistake it shows un equal . Is this way of storing the arrays in a pointer inside a strucutre is correct method. or is there any other way to do this.
EDIT:
I wanted to compare the 2 strings. The 2 strings are equal but i'm getting it as unequal.
Is the pointer a need to be stored in a structure to store the 2 arrays or is there another way of dong this.
#include <stdio.h>
#include <string.h>
int main(){
int i,flag=0,count=0;
struct n{
unsigned char b[4];
};
struct s{
unsigned char *a;
};
unsigned char *d=NULL;
struct s m[2];
struct n w[2];
strcpy(w[0].b,"eng");
strcpy(w[1].b,"fre");
d = w[1].b; // current lang
m[0].a = w[0].b; // storing the 2 lang in a pointer inside a structure
m[1].a = w[1].b;
for (i =0; i <= 1; i++) {
printf("\nm[%d].a: %s d: %s\n", i, m[i].a, d);
if (strcmp(m[i].a, d) != 0) {
printf("Not equal\n");
}
else{
printf("\nEqual\n");
}
}
return 0;
}

C - split/store string of X length into an array of structs

I'm trying to split a string every X amount of characters, and then store each line in an array of structs. However, I'm wondering what would be a short and efficient way of doing it. I thought that maybe I could use sscanf, but not very sure how to. Any help will be appreciated. So far I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st {char *str;};
int main ()
{
struct st **mystruct;
char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
size_t max = 20, j = 0; // max length of string
size_t alloc = strlen(tmp)/max + 1;
mystruct = malloc(alloc * sizeof *mystruct);
for (j = 0; j < alloc; j++)
mystruct[j] = malloc(sizeof *mystruct[j]);
const char *ptr = tmp;
char field [ max ];
int n;
while (*ptr != '\0') {
int line = sscanf(ptr, "%s", field, &n); // not sure how to use max in here
mystruct[j]->str = field;
field[0]='\0';
if (line == 1)
ptr += n;
if ( n != max )
break;
++ptr;
++j;
}
return 0;
}
So when I iterate over my struct, I can get something like:
For configuration op
tions (arch/xxx/conf
ig.in, and all the C
onfig.in files),some
what different inden
tation is used.
You could use strncpy.
FYI:
char field [ max ];
while (...) {
mystruct[j]->str = field;
Two problems with this: (1) every struct in your array is going to end up pointing at the same string, which will have the value of the last thing you scanned, (2) they are pointing to a variable on the stack, so when this function returns they will be trashed. That doesn't manifest itself visibly here (e.g. your program doesn't explode) because the function happens to be 'main', but if you moved this to a separate routine and called it to parse a string, you'd get back garbage.
mystruct doesn't need to be pointer to pointer. For a 1D array, just allocate a block N * sizeof *myarray for N elements.
A common C idiom when dealing with structs is to use typedef so you don't have to type struct foo all the time. For instance:
typedef struct {
int x, y;
} point;
Now instead of typing struct point pt you can just say point pt.
If your string is not going to change after you split it up, I'd recommend using a struct like this:
struct st {
char *begin;
char *end;
};
or the alternative:
struct st {
char *s;
size_t len;
};
Then instead of creating all those new strings, just mark where each one begins and ends in your struct. Keep the original string in memory.
One option is to do it character-by-character.
Calculate the number of lines as you are currently doing.
Allocate memory = (strlen(tmp) + number_of_lines) * sizeof(char)
Walk through your input string, copying characters from the input to the newly allocated memory. Every 20th character, insert a null byte to delimit that string. Save a pointer to the beginning of each line in your array of structs.
Its easy enough?
#define SMAX 20
typedef struct {char str[SMAX+1];} ST;
int main()
{
ST st[SMAX]={0};
char *tmp = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
int i=0,j;
for( ; (st[i++]=*(ST*)tmp).str[SMAX]=0 , strlen(tmp)>=SMAX; tmp+=SMAX );
for( j=0;j<i;++j )
puts(st[j].str);
return 0;
}
You may use (non C standard but GNU) function strndup().
#define _GNU_SOURCE
#include <string.h>
struct st {char *str;};
int main ()
{
struct st *mystruct; /* i wonder if there's need for double indirection... */
char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
size_t max = 20, j = 0; // max length of string
size_t alloc = (strlen(tmp) + max - 1)/max; /* correct round up */
mystruct = malloc(alloc * sizeof mystruct);
if(!mystruct) return 1; /* never forget testing if allocation failed! */
for(j = 0; j<alloc; j++)
{
mystruct[j].str = strndup(tmp+alloc*max, max);
}
}

Resources