Say I have a simple struct, such as this one:
struct myStruct {
uint8_t arr[10];
};
All I want to be able to do is to modify the contents of that array. However, it seems that I cannot assign the array directly (ie, I can't do something like pointerToThisStruct->arr = anArrayofSizeTen).
So here is my main method:
int main(int argc, char **argv) {
uint8_t test[10] = {0};
myStruct *struc;
struc->arr = test; //can't do this
memcpy(struc->arr, test, sizeof(test));
}
Now, I understand that direct copying over won't work, but why is memcpy also giving me a segfault? How exactly am I supposed to modify the struct array?
You need to declare an actual myStruct. Not a pointer to one. Declaring a pointer to one doesn't actually allocate any memory for the struct.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
struct myStruct {
uint8_t arr[10];
};
int main(int argc, char **argv) {
int i;
uint8_t test[10] = {0,1,2,3,4,5,6,7,8,9};
struct myStruct struc;
memcpy(struc.arr, test, sizeof(struc.arr));
printf("struc.arr[] = ");
for( i=0; i < sizeof(test); i++ )
{
printf("%d ", struc.arr[i]);
}
printf("\n");
return( 0 );
}
You are getting a segmentation fault because you didn't allocate your struct pointer.
int main(int argc, char **argv) {
uint8_t test[10] = {0};
struct myStruct *struct = malloc(sizeof(struct myStruct));
if (!struc)
return -1;
memcpy(struc->arr, test, sizeof(test));
free(struc);
return 0;
}
But, as #Chimera mentioned, you perfectly can not use a point and directly a heap-allocated structure, and access to its inner fields with the . operator
Related
I have many programs where structs are defined. And each time, I have to create a function to print the members. For example,
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
void printMyStruct(myStruct myPeople) {
printf("%s\n",myPeople.name);
printf("%s\n",myPeople.address);
printf("%d\n",myPeople.zip);
}
int main()
{
myStruct myPeople={"myName" , "10 myStreet", 11111};
printMyStruct(myPeople);
}
I know that reflection is not supported in C. And so, I write these printing functions for each struct I defined.
But, I wonder if it exists any tricks to generate automatically these printing functions. I would understand that I have to modify a little bit these functions. But, if a part of the job is done automatically, it would be great.
(This example is simple, sometimes struct are nested or I have array of structs or some fields are pointers, ...)
You can of-course print structs, but expect a lot of non-readable output:
#include <stdio.h>
#include <ctype.h>
struct example {
int x;
int y;
char c;
};
#define NOT_PRINTABLE "Not Printable"
void print_structure(const char *structure, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%ld)\t%.2X: %.*s\n", i, structure[i],
(isprint(structure[i]) ? 1 : sizeof(NOT_PRINTABLE) - 1),
(isprint(structure[i]) ? &structure[i] : NOT_PRINTABLE));
}
}
int main(int argc, char **argv) {
struct example a;
a.x = 5;
a.y = 6;
a.c = 'A';
print_structure((char *)&a, sizeof(struct example));
return 0;
}
But the issue is that, it will print the structs as it is represented in memory. So 4 byte (32 bit) integer 1 will be represented with 4 bytes, not the char '1'.
And due to the way pointers work, you cannot make out if a member is a pointer or a non-pointer.
Another issue is that structures have padding to help with alignment, and better/efficent use of memory. So you would see a lot of 0x00 in the middle.
Remember that C is a compiled language.
let's consider to use https://copilot.github.com/. it's great.
this is what i have with copilot
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
//print struct myStruct >> auto generate by codepilot after you type a comment `print struct myStruct`
void printStruct(myStruct *s) {
printf("name: %s\n", s->name);
printf("address: %s\n", s->address);
printf("zip: %d\n", s->zip);
}
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
I'm not sure why the following is producing a segmentation fault. I've defined a structure and I'm trying to store a value to it.
typedef struct {
int sourceid;
int destid;
} TEST_STRUCT;
void main( int argc, char *argv[] ) {
TEST_STRUCT *test;
test->sourceid = 5;
}
You declare a pointer to the type. You need to allocate memory for the pointer to point to:
#include <stdlib.h>
typedef struct {
int sourceid;
int destid;
} TEST_STRUCT;
int main(int argc, char *argv[]) {
TEST_STRUCT *test;
test = malloc(sizeof(TEST_STRUCT));
if (test) {
test->sourceid = 5;
free(test);
}
return 0;
}
Alternatively, you could declare the variable on the stack:
typedef struct {
int sourceid;
int destid;
} TEST_STRUCT;
int main(int argc, char *argv[]) {
TEST_STRUCT test;
test.sourceid = 5;
return 0;
}
test pointer is not pointing to any address(pointing some garbage) so it is hitting segV
TEST_STRUCT *test;
it is good practice to initialize NULL and before dereference it, check if (test != NULL) {}
then only dereference.
to solve this, first you need to create variable of TEST_STRUCT and assign address of it to test pointer or allocate memory using malloc/calloc and then try this
There are quite a few topics on this subject but I haven't been able to find a solution that's worked for me; I am getting a segmentation fault whenever I try to change student_t.member->name. Below is the typedef structure that I am required to use:
typedef struct degree_t degree_t;
typedef struct student_t student_t;
struct degree_t {
student_t* member;
int course_id;
}
struct student_t {
char* name;
int age;
}
int main(int argc, char* argv[]) {
student_t *students = malloc(sizeof(student_t) * 3);
degree_t *degrees = malloc(sizeof(degree_t));
for (int i=0; i<3; i++) {
degrees[i].course_id = 1;
degrees[i].member->name = "Bob";
}
return 0;
}
I can change degrees[i].course_id perfectly fine, but whenever I try to change degrees[i].member -> name, I get a segmentation fault.
GDB indicates that this is a result of the line degrees[i].member->name = "Bob", but I'm don't understand why, and I don't know how to effectively change the value of degrees[i].member->name
Oops, you managed to place four errors in that small program.
The signature of main() should be main(int argc, char *argv[]). argv is an array of strings found on the command line.
You allocate memory for one degree, but in the for-loop you initialize three of them. This leads to a heap corruption.
You don't initialize degrees->member, but use it.
You allocate memory for three students, but don't use it.
Try this:
struct degree_t {
student_t* member;
int course_id;
}
struct student_t {
const char* name;
int age;
}
int main(int argc, char* argv[]) {
degree_t *degrees = malloc(3 * sizeof(degree_t));
for (int i=0; i<3; i++) {
degrees[i].course_id = 1;
degrees[i].member = malloc(sizeof(student_t));
degrees[i].member->name = "Bob";
degrees[i].member->age = 23;
}
return 0;
}
Needed: A function which returns two different values (int,str)
So foo calculates smth. and stores the addresses of the two values
in the return array.
Now I want to read the values back into variables of these types.
void** foo(){
void** bar = malloc(2 * sizeof(void*));
...
return bar;
}
int main(int argc, char* argv[]){
void** result = foo();
int* val1 = (int*)result[0];
char* val2 = (char*)result[1];
}
This snippet is not compiling.
Excuse me:
the problem was not the code but that I declared it in a case branch
without any compution instructions.
int main(int argc, char* argv[]){
switch(xyz){
case a:
void** result = foo();
int* val1 = (int*)result[0];
char* val2 = (char*)result[1];
break;
}
}
Which seems not to make sense in a case.
Thanks though.
If you come up with the need to use a void**, it is a strong indication of poor program design. Just forget about this idea. void pointers in general is something you should avoid.
What you actually want to do seems to be something like this:
typedef struct
{
int i;
char c;
} something_t;
something_t* foo (void)
{
something_t* result = malloc (sizeof(*result));
...
return result;
}
int main(int argc, char* argv[]){
something_t* result = foo();
int* val1 = &result->i;
char* val2 = &result->c;
}
If the struct members need to be pointers, simply change the struct.
You should use structure to do your job
#include <stdio.h>
#include <stdlib.h>
#define STRING_WIDTH 32
struct test
{
int val1;
char *val2;
};
struct test *foo(void)
{
struct test *bar = malloc(sizeof(struct test));
if (bar != NULL)
{
bar->val1 = 0;
bar->val2 = calloc (STRING_WIDTH, 1);
if (bar->val2 == NULL)
return NULL;
}
return bar;
}
int main( void )
{
struct test *result = foo();
if (result != NULL)
{
// USE YOUR STRUCT
}
return 0;
}
Take note that mallocated memory must be freed
I would like to allocate nested data structures which are defined below with only one malloc call. Is it possible in C? If so, how can I do that?
struct s1 {
int a;
int b;
char ns1[16];
};
struct s2 {
struct s1 *ps1;
int i;
int j;
char ns2[16];
};
This is not a nested structure because ps1 is a pointer, not a structure.
malloc() works just fine with pointers. You can allocate s2 with no problem. But you will have to point the ps1 member to something valid.
A nested structure would look more like this:
struct s2 {
struct s1 x_s1;
int i;
int j;
char ns2[16];
};
And malloc() should be okay with that one as well.
A portable way to allocate space for multiple objects at once is to wrap them into a container structure:
struct PairHolder
{
struct s2 first;
struct s1 second;
};
// Postcondition: You own the result and must call free() on it (and on nothing
// else).
struct s2 * create_s2_and_s1()
{
struct PairHolder *ph = malloc(sizeof(PairHolder));
ph->first.ps1 = &ph->second;
return &ph->first;
}
After one day study, and based on previous answers. I came up with the solution below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct s1 {
int a;
int b;
char ns1[16];
};
struct s2 {
struct s1 *ps1;
int i;
int j;
char ns2[16];
};
int main(int argc, char *argv[])
{
struct s2 *ps2;
ps2 = malloc(sizeof(struct s1) + sizeof(struct s2));
ps2->ps1 = (struct s1 *)(ps2 + 1);
ps2->ps1->a = 1;
ps2->ps1->b = 2;
strcpy(ps2->ps1->ns1, "s1");
ps2->i = 3;
ps2->j = 4;
strcpy(ps2->ns2, "s2");
free(ps2);
return 0;
}