How to use a pointer to character within a c structure? - c

It is possible to declare a string of the required size using char name[size], however if I want to use char *name, how will I specify the size that I require using malloc()?
I found out that I cannot use char *name = malloc(5*1); within the structure declaration.
I have tried using
struct data
{
int age;
char *name;
};
On running this code and entering the string I encountered Segmentation fault.
How must I specify the size?

You need to specify the size of the pointer, you need to make the pointer to point to a valid memory, that's all. Moreover, it not necessary to use malloc(). You can either
allocate memory to the pointer via allocator functions, malloc() or family
make the pointer point to the address of any other char variable (or array)
To elaborate, you create a variable var of type struct data, and then, make var->name point to a valid chunk of memory.
That said, to use malloc() for allocating required size of memory, you need to supply the required size as the argument to malloc() (in bytes).

let's say you create a variable a of the type struct data
struct data a;
Now allocate memory to the name member of a i.e,
a.name = malloc(size_of_name + 1); //+1 for '\0' character at the end
Now you can use a.name to store and use the string
Don't forget to free the allocated data before terminating the program. for this use free(a.name).

You need to allocate the memory like:
data* r = malloc(sizeof(data));
r->name= malloc(20);
assuming the name can hold 20 chars

You'd need to supply a way to initialize your structure. For example:
void init_data (struct data *p_data) {
if (p_data)
p_data->name = malloc(STR_LEN);
}
And you should couple that with a function to free the memory:
void release_data (struct data *p_data) {
if (p_data)
free(p_data->name);
}
It would than be called whenever you want to use your structure.
struct data d;
init_data(&d);
/* use d */
release_data(&d);

Related

Assign characters to arrow pointer in c

struct room
{
char venue[15]; //variable
}
*stream;
.
.
.
void idealounge(){
int i,idealounge[10];
char room1[10]="MMLC";
*** ** stream->venue = room1;*****
}
This is a room booking system.
The name of the room called MMLC.
I expect it can store "MMLC" to stream->venue but it shows errors like "incompatible values" etc.
The statement:
char venue[15];
declares venue to be an array of size 15 of char. Then,
char room1[10]="MMLC";
initialises the first 4 bytes of room1 with the string literal "MMLC", setting the rest to \0.
Then,
stream->venue = room1;
is invalid, because venue is an array, not a pointer. Arrays are not modifiable l-values. You can't assign arrays like this.
If you want to copy the contents of room1 to the contents of venue, use standard strcpy().
That being said,
struct room
{
char venue[15]; //variable
}
*stream;
only allocates space for the pointer, which is uninitialized and isn't pointing to anything meaningful. So first allocate memory and initialise the pointer:¹
stream = malloc (sizeof (struct room));
Then check if it succeeded:²
if (!stream) {
perror ("malloc()");
/* handle error here...*/
}
Now perform the string copy.
Alternatively, you can allocate the struct with automatic storage duration, which is simpler and less error-prone:
struct room bedroom;
and then assign it's address to the pointer:
stream = &bedroom;
This avoids the need for dynamic memory allocation, which you might fail to free() later on.
[1] — NB that I do not cast the result of malloc(). malloc() returns a generic void *, or void pointer, which is automatically promoted to the correct type. So there's no need to cast, and doing so might hide a potential bug.
See also: Do I cast the result of malloc?
[2] — POSIX-compliant systems set errno on malloc() failure, the above code snippet assumes it does. But you may not wish to take it for granted, and handle the error in another way.
struct room
{
char venue[15]; //variable
}
*stream = NULL;
void idealounge() {
int i;
int idealounge[10];
char room1[10]="MMLC";
stream = (struct room *)malloc(sizeof(struct room));
strcpy(stream->venue, room1);
}
You should write this way.

Different arrays in dynamic struct, creation, writting, reading

Strait to the point.
I have a struct with a string, char and int.
The struct is created dynamically because i will need it in different parts of my program.
struct A
{
char staticString[20];
char* dynamicString;
char character;
int integer;
};
I know if i want to create a struct i call:
A example = (A)malloc(sizeof(A));
In order to populate the dynamicString and int i used:
example->dynamicString = (char*)malloc(sizeof(char*));
example->integer = (int)malloc(sizeof(int));
Unfourtanetly when i tried to populate staticString and char it didn't worked.
Don't even ask what was my code for those, i tried a lot of combinations from everywhere.
In addition to that can somebody show me examples how to write/read those values?
Thanks in advance.
First things first:
You're using C, and by the way you've defined the structure, you need to declare the pointer like so:
struct A *example;
Next, malloc returns a pointer, so you need to cast to a pointer (and not to a structure):
(struct A *)malloc(sizeof(struct A));
Secondly, I'm not sure why but hey:
- you're trying to dynamically allocate an int in the structure. As I said previously, malloc returns a pointer, so in your structure you need an int pointer like so "int *integer;"
- you're trying to allocate a dynamic string, however you're not doing it properly, here is what I think you want
example->dynamicString = (char *)malloc(sizeof(char) * 10);
Where 10 is the size of your dynamic string.
Edit:
you may also populate the integer in your struct statically or dynamically, but I think you intended the static approach:
example->integer = 123;
The dynamic approach would be (assuming you have int *integer in your struct):
example->integer = (int *)malloc(sizeof(int));
*(example->integer) = 123;
Every time you create a new struct the memory in the heap is set to size of :
sizeof(char)*20 + sizeof(char pointer) +sizeof(char)+ sizeof(int).
If you want to save a string that will be pointed to by your char pointer- then you ask for allocation in heap for the size of that string- and malloc returns the pointer to that memory allocation on heap.
So, you already have a space for your char array, char pointer, char and int that was allocated when you asked to make a new struct and do not need to allocate it again.
also, keep in mind malloc returns a pointer to the allocated place on the heap- so if you malloc(sizeof(int)) you get a pointer to a memory allocation for an int on the heap- which is pointed to by a int pointer Not an int.
good luck!

A segmentation fault with malloc while populating a structure fields in a function

I have a struct defined as
struct _element;
typedef struct _element Element;
struct _element {
char* StudentName;
char* StudentID;
int StudentMarks;
};
A pointer to an Element struct is declared globally as
Element * ePtr;
Now I have a function that returns a pointer to an Element struct. This is defined as shown below. The same ePtr which was declared globally is populated in this function and then returned.
Element * CreateElement(char * jName, char * jID, int jMarks)
{
printf("CreateElement \n");
puts(jName); puts(jID); printf("%d\n",jMarks);
ePtr->StudentName = (char*)malloc(sizeof(char)*strlen(jName));
strcpy(ePtr->StudentName, jName);
printf("After Creation \n");
puts(ePtr->StudentName);
return ePtr;
}
I am calling this function using
ePtr = CreateElement(iName,iID,iMarks);
from another function. The values stored in the parameters are correct, as shown by puts and printf commands just below the function call line.
My problem is that I'm getting a segmentation fault at the
ePtr->StudentName = (char*)malloc(sizeof(char)*strlen(jName));
line. I checked the same using gdb.
Are you allocating any memory for ePtr?
Just declaring a pointer to this struct globally isn't enough: you'll need to malloc some memory for it also: ePtr = malloc(sizeof(Element);.
Also be sure to add an extra slot in the malloc for your strings for the null terminator.
Generally, always initialize your pointers to NULL - you can do that when you declare the global: Element *ePtr = NULL;. Furthermore, try to get your ePtr out of the global-scope, and, check for NULL before you use a pointer, as with ePtr in your CreateElement method.
You need to assign some memory for ePtr before you can assign memory to the char* that it contains. Do a malloc on your ePtr at the start of the function.
There is also little point in declaring ePtr globally, but this isn't what is breaking the program.
ePtr = (Element*)malloc(sizeof(Element));
You should probably also check if ePtr is null after this before using it (can be null if out of memory as well as some other issues).
You don't assign any memory to
ePtr = (Element*)malloc(sizeof(Element));
before you start assigning values to it and ultimately return it from the function.
Also you need to allow space for the nul terminator of your string
ePtr->StudentName = (char*)malloc(sizeof(char)*(strlen(jName) + 1));
Finally don't forget to allocate memory for and copy the value of the ID, and copy the studentMarks into Element.
Remember, the Element is fixed-size. It needs memory to hold the two char * as well as the one int. It does not matter that the strings are variable length when allocating memory for Element.

how to convert a dynamically numerical string into a dynamically array of integers

struct integer* convert_integer(char* stringInt)
{
struct integer* convertedInt_1;
char* stringArray3 = (char *) malloc (sizeof(char));;
free(stringArray3);
stringArray3 = stringInt;
convertedInt_1->digits = atoi(stringArray3);
stringArray4 = stringInt;
}
this is a sample of the code. this code is giving me an error when i use the standard library from c "Warning: assignment makes pointer from integer to without a cast"
so i need to know how to convert a dynamically numerical string into dynimacally struct integer
You do not need any dynamic allocation for char string here, nor do you need an additional char * pointer.
struct integer* convert_integer(char* stringInt)
{
/*Allocate memory to structure,You cannot return pointer to local structure*/
struct integer* convertedInt_1 = (struct integer*)malloc(sizeof(*convertedInt_1));
/*Convert the string to integer*/
int i = atoi(stringInt);
/*Assign converted integer to structure member*/
convertedInt_1->digits = i;
/*return pointer to heap allocated structure*/
return convertedInt_1 ;
}
There are a lot of problems with this code, but I'll try to walk you through them.
One, you malloc only one char worth of memory, not the amount of memory needed to hold your array. You really need to include an argument for the size of the array to be changed if the string is not null terminated.
Second, you're trying to use memory after you free it. This is bad. Very bad. You should only free memory after you're finished with it.
Next, you're trying to atoi the entire array at once. This is going to try to change the entire string into one number, not one int.
What I think you want, is to convert each character from stringInt to a (single digit) int in your result. For this, use a for loop to iterate through the array.
I'm pretty sure you want to be using int and not integer.
Last, you forgot to return anything - this doesn't compile.

How to create a structure with two variable sized arrays in C

I am writing a light weight serialization function and need to include two variable sized arrays within this.
How should I track the size of each?
How should I define the struct?
Am I going about this all wrong?
EDIT: the result must be a contiguous block of memory
This resolves to something like
typedef struct
{
size_t arr_size_1, arr_size_2;
char arr_1[0/*arr_size_1 + arr_size_2*/];
} ...;
The size(s) should be in the front of the dynamic sized data, so that it doesn't move when expanding your array.
You cannot have 2 unknown sized arrays in your struct, so you must collapse them into one and then access the data relative from the first pointer.
typedef struct MyStruct_s
{
int variable_one_size;
void* variable_one_buf;
int variable_two_size;
void* variable_two_buf;
} MyStruct;
MyStruct* CreateMyStruct (int size_one, int size_two)
{
MyStruct* s = (MyStruct*)malloc (sizeof (MyStruct));
s->variable_one_size = size_one;
s->variable_one_buf = malloc (size_one);
s->variable_two_size = size_two;
s->variable_two_buf = malloc (size_two);
}
void FreeMyStruct (MyStruct* s)
{
free (s->variable_one_buf);
free (s->variable_two_buf);
free (s);
}
Since the data should be continuous in memory it is necessary to malloc a chunk of memory of the right size and manage it's contents more or less manually. You probably best create a struct that contains the "static" information and related management functions that do the memory management and give access to the "dynamic" members of the struct:
typedef struct _serial {
size_t sz_a;
size_t sz_b;
char data[1]; // "dummy" array as pointer to space at end of the struct
} serial;
serial* malloc_serial(size_t a, size_t b) {
serial *result;
// malloc more memory than just sizeof(serial), so that there
// is enough space "in" the data member for both of the variable arrays
result = malloc(sizeof(serial) - 1 + a + b);
if (result) {
result->sz_a = a;
result->sz_b = b;
}
return result;
}
// access the "arrays" in the struct:
char* access_a(serial *s) {
return &s->data[0];
}
char* access_b(serial *s) {
return &s->data[s->sz_a];
}
Then you could do things like this:
serial *s = ...;
memcpy(access_a(s), "hallo", 6);
access_a(s)[1] = 'e';
Also note that you can't just assign one serial to another one, you need to make sure that the sizes are compatible and copy the data manually.
In order to serialize variably-sized data, you have to have a boundary tag of some sort. The boundary tag can be either a size written right before the data, or it can be a special value that is not allowed to appear in the data stream and is written right after the data.
Which you choose depends on how much data you are storing, and if you are optimizing for size in the output stream. It is often easier to store a size before-hand, because you know how big to make the receiving buffer. If you don't then you have to gradually resize your buffer on load.
In some ways, I'd do things like Dan Olson. However:
1) I'd create the final struct by having two instances of a simpler struct that has just one variable array.
2) I'd declare the array with byte* and use size_t for its length.
Having said this, I'm still not entirely clear on what you're trying to do.
edit
If you want it contiguous in memory, just define a struct with two lengths. Then allocate a block big enough for both blocks that you want to pass, plus the struct itself. Set the two lengths and copy the two blocks immediately after. I think it should be clear how the lengths suffice to make the struct self-describing.

Resources