I want to allocate some memory to one of the members of a dynamic structure, dynamically. But I don't know what do I do and also, i don't know how to use them after allocating.
This is my code work :
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int main()
{
struct Sample_Structure {
float *Number_ptr; // This is the pointer to allocate some memory, dynamically.
int Num1;
int Num2;
} *struct_ptr;
struct_ptr = (struct Sample_Structure*) malloc (sizeof (struct Sample_Structure));
if (!struct_ptr)
{
printf("An error occurred while allocating memory.\n");
exit(1);
}
// I don't know what do I write here to allocate some memory to the pointer, "Number_ptr" in the structure
printf("Enter your number 1 and 2 : ");
scanf("%d%d", &struct_ptr->Num1, &struct_ptr->Num2);
system("cls");
printf("Your numbers are %d and %d\n", Struct_ptr->Num1, Struct_ptr->Num2);
return 0;
}
I wrote some comments for you to know where did I want to allocate some memory to the pointer of the structure, "Sample_Structure". Generally, can we do that? If yes, how?
you can allocate memory the for it , the same way you allocated for *struct_ptr
like this
struct_ptr->Number_ptr = (float *) malloc(sizeof(float));.
and when you want to scan data for it you shouldn't use & for it:
scanf("%d%d%f", &struct_ptr->Num1, &struct_ptr->Num2, struct_ptr->Number_ptr);
and in printf you should use * for it:
printf("Your numbers are %d and %d\nand %f\n", struct_ptr->Num1, struct_ptr->Num2, *struct_ptr->Number_ptr);
also you should this capital S to lowercase letter in this printf:
printf("Your numbers are %d and %d\n", struct_ptr->Num1, struct_ptr->Num2);
also note that you don't need to cast for malloc and it's not good to that , unless you're using c++ compiler.
int main()
{
struct Sample_Structure {
float* Number_ptr;
int Num1;
int Num2;
} *struct_ptr;
struct_ptr = (struct Sample_Structure *)malloc(sizeof(struct Sample_Structure));
if (!struct_ptr)
{
printf("An error occurred while allocating memory.\n");
exit(1);
}
struct_ptr->Number_ptr = (float *) malloc(sizeof(float));
printf("Enter your number 1 and 2 : ");
scanf("%d%d%f", &struct_ptr->Num1, &struct_ptr->Num2, struct_ptr->Number_ptr);
system("cls");
printf("Your numbers are %d and %d\nand %f\n", struct_ptr->Num1, struct_ptr->Num2, *struct_ptr->Number_ptr);
return 0;
}
For example, you want to allocate memory for 10 floats for Number_ptr:
struct_ptr->Number_ptr = malloc( sizeof(float) * 10 );
Correction:
Change this line
printf("Your numbers are %d and %d\n", Struct_ptr->Num1, Struct_ptr->Num2);
^ ^
to
printf("Your numbers are %d and %d\n", struct_ptr->Num1, struct_ptr->Num2);
And, you're leaking memory. You need to deallocate memory using free() after use. Make sure for every allocation e.g. malloc(), there is corresponding deallocation e.g. free().
Also, validate if the memory is allocated or not.
Here's a small example for your reference (live):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define MAX 10
typedef struct S
{
int* ilist;
} S;
int main()
{
S s;
s.ilist = malloc( MAX * sizeof(*s.ilist) ); // allocation
if ( s.ilist == NULL )
{
printf("Unable to allocate memory!\n");
return -1;
}
// An assertion may also be used like this (Header: <assert.h>):
// assert( s.ilist != NULL );
for ( int i = 0; i < MAX; ++i )
{
s.ilist[i] = i + 1; // store elements
}
for ( int i = 0; i < MAX; ++i )
{
printf("%d ", s.ilist[i]); // read elements
}
free( s.ilist ); // deallocation
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
Related
I'm trying to teach C to myself and I'm struggling with what it looks like a very basic thing. I have a struct with a char pointer and I want to dynamically allocate memory and free it once done. What I understand is that I need to allocate memory for both the struct and the char pointer but it looks like I'm missing something because I'm getting a Segmentation fault on the sprintf line.
As an exercise to understand and use malloc and free, I'm trying to build an easy program that takes an int as input and outputs a table with the factorials of all the numbers from 0 to input. Each table entry has its index (int), the result of the factorial (long long int) and the result but in an array of chars format (this is the problematic one).
Here's what I have until now:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str = NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=0; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
I'm probably missing something very obvious and making a silly mistake when allocating the memory for the fact_table[i].str, but I'm struggling to make it work.
In addition to the comments about freeing the memory for n >= 2, if you look at your test after the malloc:
if (fact_table[i].str = NULL) {
You are setting your pointer to NULL. Instead you should write:
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if ( fact_table[i].str == NULL) {
shout("malloc");
}
Just some little recommendation here. This mistake generates a warning on most compiler if you compile using -Wall:
fact.c: In function ‘main’:
fact.c:53:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (fact_table[i].str = NULL) {
^~~~~~~~~~
Also, in order to make sure the compiler will complain if you forget a =, you can compare the values of a variable and of a constant placing the constant on the left: if you write if (NULL = fact_table[i].str), your compiler will complain and notify you with the error.
I reproduced this issue on my setup. We need to fix two issues before program runs ok.
change 'fact_table[i].str = NULL' to 'fact_table[i].str == NULL'. Your previous command directly set 'str' to NULL, which is not expected. This is the reason you met segment error.
In Free memory part, you need to start from index 2. You cannot free memory which doesnot belong to you.
Below code can work well in my setup.
Wish this can help you.
**
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str == NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=2; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
**
I am trying to make a simple example of a array that increases with its input. The input is a series of numbers and the end of this series is a zero. What I thought of was to increase my array every time a new number is read, but for some reason this does not seem to work since I get an error:
Realloc(): invalid pointer
This is my current code:
#include <stdio.h>
#include <stdlib.h>
int *resizeIntArray(int *series, int newSize) {
int *newSeries = realloc(series, newSize * sizeof(int));
if (newSeries == NULL) {
printf("Error: Memory allocation failed");
exit(-1);
}
return newSeries;
}
int main(int argc, char *argv[]) {
int number;
scanf("%d", &number);
int *numbers;
int size = 0;
while (number != 0) {
numbers = resizeIntArray(numbers, size + 1);
printf("%d ", number);
scanf("%d", &number);
size++;
}
}
You are passing an uninitialised variable to your function, in turn passed to realloc, which needs either a pointer to previously allocated memory, or NULL.
So initialise that variable:
int *numbers = NULL;
There are multiple issues in your code:
you do not initialize numbers to NULL, so realloc() invokes undefined behavior the first time it is called. This is causing the problem you observe.
you do not check the return value of scanf(), causing a potential endless loop and undefined behavior if the input stream does not contain a 0 number.
you do not store the number in the reallocated array...
you do not free the array (minor).
you do not return 0 at the end of main() (minor).
Here a simpler and safer version:
#include <stdio.h>
#include <stdlib.h>
int *resizeIntArray(int *series, int newSize) {
int *newSeries = realloc(series, newSize * sizeof(int));
if (newSeries == NULL) {
printf("Error: Memory allocation failed");
exit(-1);
}
return newSeries;
}
int main(int argc, char *argv[]) {
int number;
int *numbers = NULL;
int i, size = 0;
/* reading the numbers */
while (scanf("%d", &number) == 1 && number != 0) {
numbers = resizeIntArray(numbers, size + 1);
numbers[size++] = number;
}
/* printing the numbers */
for (i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
free(numbers);
return 0;
}
You can try an approach like this. This includes:
Memory checking, with appropriate error messages.
use of malloc() and realloc() to allocate and reallocate memory.
Allocates sufficient space when needed on run-time.
Appropriately checks return value of scanf().
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define EXIT 0
void exit_if_null(void *ptr, const char *msg);
int
main(int argc, char const *argv[]) {
int *numbers = NULL;
int number, num_size = 1, count = 0, i;
/* initial allocation of memory */
numbers = malloc(num_size * sizeof(*numbers));
/* small error checking, to be safe */
exit_if_null(numbers, "Initial Allocation");
/* Reading in numbers */
printf("Enter numbers(0 to end): ");
while (scanf("%d", &number) == 1 && number != EXIT) {
/* valid number found, but is there space? */
if (num_size == count) {
num_size *= 2;
/* resize run-time array */
numbers = realloc(numbers, num_size * sizeof(*numbers));
exit_if_null(numbers, "Reallocation");
}
numbers[count++] = number;
}
/* print out numbers */
printf("Your numbers stored in array:\n");
for (i = 0; i < count; i++) {
printf("%d ", numbers[i]);
}
/* free allocated memory, very important */
free(numbers);
return 0;
}
/* helper function for error checking */
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
First you should first allocate some memory before reallocate it. So your code will change as:
#include <stdio.h>
#include <stdlib.h>
int *resizeIntArray(int *series, int newSize){
int *newSeries = realloc(series,newSize*sizeof(int));
if(newSeries == NULL){
printf("Error: Memory allocation failed");
exit(-1);
}
return newSeries;
}
int main(int argc, char* argv[]) {
int number;
scanf("%d",&number);
int *numbers=malloc(sizeof(int));///CHANGED
int size = 1;///CHANGED
while(number != 0){
numbers = resizeIntArray(numbers,size +1);
printf("%d ",number);
scanf("%d",&number);
size++;
}
}
But white you are doing is quite not efficent. A realloc() function hides a free() a malloc() and the worst one: memcpy(). So if you realloc() at each new item, you are going to have a bad time... O(n^2) exactly.
the best way to do it is to allocate a buffer of memory:
struct vector
{
int *numbers;
size_t size;
size_t i;
}
#define DEFAULTBUF 100
int main()
{
struct vector v;
v.numbers=malloc(sizeof(int)*DEFAULTBUF);
v.size=DEFAULTBUF;
v.i=0;
scanf("%d",&number);
while(number != 0 && v.numbers){
if (v.i->=v.size)
{ v.size+=v.size
v.numbers=realloc(v.numbers,sizeof(int)*v.size);
///i leave to you the error handling
}
v.i++;
printf("%d ",number);
scanf("%d",&number);
}
}
The correct use of realloc() malloc() and similar is very important. And also the increasing ratio of the resize. For the datastructure I ever double it. For text I proceed linearly
i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));
I am learning pointer in c
i have written a small program , but i am getting segmentaion fault
i dont know where i am having the issue
please let me know the issue with the code , it is an array of pointers to string ,
which is in a pointer to structure .
# include <stdio.h>
#include <stdlib.h>
# include <string.h>
char *sum(char **sol) ;
char *summer_sum(char*** solcs) ;
int main()
{
char* datum ="teststring";
sum(&datum);
}
char *sum(char** sol)
{
printf("\n value is : %s",*sol);
summer_sum(&sol);
return "1" ;
}
char *summer_sum(char*** solcs)
{
int i=0;
typedef struct
{
char *asg[40];
}nlist;
nlist *n1;
for( i=0 ; i<= 38 ;i++)
{
n1->asg[i] = calloc(1,1*sizeof(*solcs));
strcpy(n1->asg[i],**solcs);
printf("\n %d value is : %s",i,n1->asg[i]);
}
return NULL;
}
n1 is used uninitialized:
n1->asg[i] = calloc(1,1*sizeof(*solcs));
On the other hand, if you want to allocate enough space for the use of strcpy, you must use strlen instead of sizeof
And you don't need a double or triple pointer, your code simplified:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sum(char *sol);
char *summer_sum(char *solcs);
int main(void)
{
char *datum = "teststring";
sum(datum);
}
void sum(char *sol)
{
printf("\n value is : %s", sol);
summer_sum(sol);
}
char *summer_sum(char *solcs)
{
int i = 0;
size_t len;
typedef struct {
char *asg[40];
} nlist;
nlist *n1 = malloc(sizeof(*n1));
if (n1 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
len = strlen(solcs); /* No need to compute len on each iteration */
for (i = 0; i <= 38; i++) { /* you are filling 39 and declared 40 */
n1->asg[i] = calloc(1, len);
/* Always check the result of (m/c/re)alloc */
if (n1->asg[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(n1->asg[i], solcs);
printf("\n %d value is : %s", i, n1->asg[i]);
/* Don't forget to free */
free(n1->asg[i]);
}
free(n1);
return NULL;
}
Before using n1->... You will have allocate memory to n1 as well using calloc()
There are two problems which involves dynamic memory allocation in your code:
n1 is not initialized, you should add a statement like n1 = malloc(sizeof(*n1)); before the for statement in summer_sum()
you did not allocate enough space for each asg[i], you should allocate spaces for these asg[i] by n1->asg[i] = malloc(strlen(**solcs) + 1);
You are using your pointer n1 uninitialized. Your program invokes undefined behavior. In such case you may get either expected or unexpected result.
Second, you are missing a closing brace } in function summer_sum.
I want to use an array of string the same as this:
char arr[][20] = {"username1", "username2"};
after i have not problem to get values, for example :
printf("%s", arr[0]); // for "username1"
i have problem to insert new string to this array, something like this!? :
arr[2] = "username3"; // or sprintf(arr[2], "%s", "username3");
You're trying to insert a char* into an array of char[20]. That won't work. You could use strcpy as
strcpy(arr[2], "username3");
if you had allocated sufficient space for a third string, which you haven't. I suggest you read up on malloc and friends; you can't just append a string to this array.
With this static initialization, arr will not dynamically resize to hold a new entry (pointers to entries in the stack generally don't like being written to).
In order for this to work, arr should be of char ** and allocated properly:
// allocate enough for three entries in arr
char **arr = (char **) malloc(3 * sizeof(char *));
The wrong way of doing this would be as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char arr[][20] = {"username1", "username2"};
printf("%s\n", arr[0]);
printf("%s\n", arr[1]);
printf("sizeof arr : %d \n", sizeof(arr)/sizeof(*arr));
strcpy(arr[2],"username3");
printf("%s\n", arr[2]);
printf("sizeof arr : %d \n", sizeof(arr)/sizeof(*arr));
return 0;
}
because, when you write something like the below
char arr[][20] = {"username1", "username2"};
The first dimension is automatically calculated based on the given initializer, in this case, it is 2 (i.e. index 0 and 1).
Later when you try to access (read or write), the third element i.e. index 2, it is a undefined behavior.
If you want to increase the first dimension of a 2d array, the correct way of doing that would be as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LEN 20
int main(void)
{
char **arr = NULL;
int n=2, n1;
int i;
if ((arr = malloc(sizeof(char *) * n)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for (i=0; i<n ; i++) {
if ((arr[i] = malloc(sizeof(char) * LEN)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
}
strcpy(arr[0], "username1");
strcpy(arr[1], "username2");
printf("%s\n", arr[0]);
printf("%s\n", arr[1]);
/* add 5 more elements to arr */
n1 = 5;
if ((arr = realloc(arr, sizeof(char *) * (n + n1))) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for (i=n; i<n1+n ; i++) {
if ((arr[i] = malloc(sizeof(char) * LEN)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
}
strcpy(arr[2], "username2");
strcpy(arr[3], "username3");
strcpy(arr[4], "username4");
strcpy(arr[5], "username5");
strcpy(arr[6], "username6");
/* if you uncomment the below, it will lead to undefined behavior */
//strcpy(arr[7], "username7");
for (i=0; i<n+n1 ; i++)
printf("%d : %s \n", i, arr[i]);
for (i=0; i<n+n1 ; i++)
free(arr[i]);
free(arr);
return 0;
}
$ ./a.out
username1
username2
0 : username1
1 : username2
2 : username2
3 : username3
4 : username4
5 : username5
6 : username6
$
Hope this helps!
C does not have dynamically growing data structures built-in. If you want an array that can hold an increasing number of elements, you need to involve dynamic memory allocation. This is usually done using the realloc() function, which can be used to allocate and then re-allocate a memory block, so that you can grow the allocation as needed.