You can't call a function from within a struct definition. You should instead simply keep your first struct definition with the large string inside, and then do malloc(sizeof(p_msg)) when you want to create one.
Or you can keep it with the pointer inside, and remember to initialize that pointer with the result of malloc() every time you create a struct instance.
If you have a function taking the struct by pointer, you can do this:
int extMsg(p_msg *msgBuffer)
{
msgBuffer->longSize = 12;
msgBuffer->hello = malloc(12);
snprintf(msgBuffer->hello, 12, "hello %d", 42);
return 0;
}
Answer from John Zwinck on Stack OverflowHey friends,
I'm sure somebody on the internet jas alread answered this, but I honestly haven't found a suitable answer for me.
Let's say we have a struct like this:
typedef struct {
char *name;
int age;
} Human;And a kind of "constructor" function like this:
Human *human_new(char *name, int age)
{
Human *this = (Human *) malloc(sizeof(Human));
this->name = name;
this->age = age;
return this;
}
My question is, do I need to allocate memory for the char pointer name of the struct or is the assignment of this->name enough?
You can't call a function from within a struct definition. You should instead simply keep your first struct definition with the large string inside, and then do malloc(sizeof(p_msg)) when you want to create one.
Or you can keep it with the pointer inside, and remember to initialize that pointer with the result of malloc() every time you create a struct instance.
If you have a function taking the struct by pointer, you can do this:
int extMsg(p_msg *msgBuffer)
{
msgBuffer->longSize = 12;
msgBuffer->hello = malloc(12);
snprintf(msgBuffer->hello, 12, "hello %d", 42);
return 0;
}
You need to use pointer types, consider this code:
#include <stdlib.h>
#include <string.h>
typedef struct {
int longSize;
char * hello;
} p_msg;
int main()
{
p_msg msg;
//zeroing memory to set the initial values
memset(&msg, 0, sizeof(p_msg));
//storing the size of char array
msg.longSize = 260000;
//dynamically allocating array using stored value
msg.hello = (char *)malloc(msg.longSize);
//using msg struct in some function
int retVal = someFunc(&msg);
//free hello array after you don't need it
free(msg.hello);
msg.hello = 0;
}
c - Allocate memory for char array pointer of struct inside function - Stack Overflow
Char, Malloc, and Struct Arrays - Stack Overflow
c - Allocating char array using malloc - Stack Overflow
c - Malloc an array inside a struct - Stack Overflow
Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.
This illustrates how to allocate memory for the members of a single struct line:
typedef struct
{
char* addr;
char* inst;
}LINE;
LINE line;
int main(void)
{
strcpy(line.addr, "anystring"); //will fail
line.addr = malloc(80);
line.inst = malloc(80);
strcpy(line.addr, "someString");//success;
strcpy(line.inst, "someOtherString");//success;
}
For array of struct line...
typedef struct
{
char* addr;
char* inst;
}LINE; //same struct definition
LINE line[10]; //but create an array of line here.
int main(void)
{
int i;
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
//when done, free memory
for(i=0;i<10;i++)
{
free(line[i].addr);
free(line[i].inst);
}
}
Added to address comment
Addressing the comment under this answer from @Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
Become:
for(i=0;i<10;i++)
{
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
}
One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:
Rather than
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
The code should include
line[i].addr = strdup("someString");
if(!line[i].addr)
{
//error handling code here
}
line[i].inst = strdup("someOtherString");
if(!line[i].inst)
{
//error handling code here
}
Just replace
_st->mark = malloc(2 * sizeof(char));
With
(*_st)->mark = malloc(2 * sizeof(char));
_st is a pointer wich content is the address of the struct, so ...
1) first you need to dereference _st, and...
2) second, with the value you get, you point to the field mark
That's all !
try to avoid too many *s in your code,
was able to run it after making some changes, please refer to the ideone link in the next line.
http://ideone.com/Ow2D2m
#include<stdio.h>
#include<stdlib.h>
typedef struct student* Student; // taking Student as pointer to Struct
int initMemory(Student );
struct student {
char* mark; /* or array[2] like array[0] = 'A' , array[1] = 'B' */
int age;
int weight;
};
typedef enum{
MEMORY_GOOD,
MEMORY_BAD} Status;
int main(int argc, char* argv[]) {
Status status;
Student john; /* Pointer to struct */
/* Function call to allocate memory*/
status = initMemory(john);
printf("got status code %d",status);
}
int initMemory(Student _st){
_st = (Student)malloc(sizeof(Student));
printf("Storage size for student : %d \n", sizeof(_st));
if(_st == NULL)
{
return MEMORY_BAD;
} else {
char* _tmp = malloc(2*sizeof(char)); /* error: request for member 'mark' in something not a structure or union */
_st->mark = _tmp;
return MEMORY_GOOD;
}
}
Yes, it's a matter of style, because you'd expect sizeof(char) to always be one.
On the other hand, it's very much an idiom to use sizeof(foo) when doing a malloc, and most importantly it makes the code self documenting.
Also better for maintenance, perhaps. If you were switching from char to wchar, you'd switch to
Copywchar *p = malloc( sizeof(wchar) * ( len + 1 ) );
without much thought. Whereas converting the statement char *p = malloc( len + 1 ); would require more thought. It's all about reducing mental overhead.
And as @Nyan suggests in a comment, you could also do
Copytype *p = malloc( sizeof(*p) * ( len + 1 ) );
for zero-terminated strings and
Copytype *p = malloc( sizeof(*p) * len ) );
for ordinary buffers.
It serves to self-document the operation. The language defines a char to be exactly one byte. It doesn't specify how many bits are in that byte as some machines have 8, 12, 16, 19, or 30 bit minimum addressable units (or more). But a char is always one byte.
The problem is that you're allocating space for the string, but you're not allocating the struct at all. c remains set to NULL and you're trying to dereference it.
Allocate space for the struct before assigning to its members
prod_t *c = malloc(sizeof(prod_t));
And, as a sidenote for your next-to-fix error: this field doesn't exist
c->stock
You need to allocate space for the struct before you can assign to the string member:
prod_t *c = malloc(sizeof(prod_t));
Also see Do I cast the result of malloc?