I have a question about the following program:
It prints:
dst->val in f1=6
dst.val in main=-528993792
I want to fix this program so it will print
dst.val in main=6
How can I do this?
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct my_struct myStruct;
struct my_struct
{
int val;
};
myStruct *f2(void)
{
myStruct *dst = malloc(sizeof(myStruct));
dst->val = 6;
return dst;
}
void f1(myStruct *dst)
{
dst = f2();
printf("**dst->val in f1=%d\n", dst->val);
}
int main()
{
myStruct dst;
f1(&dst);
printf("**dst.val in main=%d\n", dst.val);
}
void f1(myStruct *dst){
myStruct *p = f2();
printf("**dst->val in f1=%d\n", p->val);
//dst is the address that was copied on the stack.
dst->val = p->val;//There is no meaning If you do not change the contents.
free(p);
}
Return your structure by value; don't use pointers and dynamic allocation:
myStruct f2(void)
{
myStruct dst;
dst.val = 6;
return dst;
}
Then f1 will use the pass-by-pointer concept more conventionally:
void f1(myStruct *dst)
{
*dst = f2();
printf("**dst->val in f1=%d\n", dst->val);
}
(actually, I am not sure if it's called "pass-by-pointer" or "pass-by-reference"; probably the latter is correct)
Related
I am not able to initialize all three pointers to struct S, and I don't know why.
I am using a fixed-length array as stack to store values.
The header file is created this way to hide information (struct S), and should be kept as generic as possible.
main.c
// main.c
#include <stdio.h>
#include "stack_exercise4.h"
int main(void) {
Stack *stack_1, *stack_2, *stack_3;
int a, b;
make_empty(stack_1);
make_empty(stack_2);
make_empty(stack_3);
return 0;
}
Problem is, after Stack *stack_1, *stack_2, *stack_3, only stack_2 has a valid address for Struct stack. stack_1 and stack_3 have some strange looking addresses, and I can't assign any values to stack_1->top, nor stack_3->top. What is the problem?
header file
// stack_exercise4.h
#ifndef STACK_EXERCISE4_H
#define STACK_EXERCISE4_H
#include <stdbool.h> /* C99 only */
typedef struct S Stack; /* incomplete type to hide the content
of S. */
void make_empty(Stack *s);
bool is_empty(const Stack *s);
bool is_full(const Stack *s);
void push(Stack *s, int i);
int pop(Stack *s);
#endif
stack source file
// stack_exercise4a.c
#include "stack_exercise4.h"
#include <stdio.h>
#define MAX_STACK_SIZE (10)
struct S {
int top;
int contents[MAX_STACK_SIZE];
};
void make_empty(Stack *s) {
s->top = 0;
}
bool is_empty(const Stack *s) {
return (s->top <= 0);
}
bool is_full(const Stack *s) {
return (s->top >= MAX_STACK_SIZE - 1);
}
void push(Stack *s, int i) {
if (!is_full(s)){
(s->contents)[s->top++] = i;
} else {
printf("Failed to push, Stack is full.\n");
}
}
int pop(Stack *s) {
return (s->contents)[s->top--];
}
The stack pointers must point on memory spaces before being dereferenced in make_empty(). Something like this could be the starting point: make_empty() allocates the memory space.
void make_empty(Stack **s) {
(*s) = (struct S *)malloc(sizeof(struct S));
(*s)->top = 0;
}
And so the initialization of the pointers would be:
make_empty(&stack_1);
make_empty(&stack_2);
make_empty(&stack_3);
Declare stack_X on stack instead.
#include <stdio.h>
#include "stack_exercise4.h"
int main(void) {
Stack stack_1 = {0}, stack_2 = {0}, stack_3 = {0};
int a, b;
make_empty(&stack_1);
make_empty(&stack_2);
make_empty(&stack_3);
return 0;
}
Otherwise, I't would need to have constructor/destructor for your Stack data structure e.g new_stack(Stack *ptr) del_stack(Stack *ptr). For beginner, I would recommend to use stack instead of heap (stay away from malloc).
I am new in C and literally trying to return pointer from my function to the pointer variable and have this "[Warning] assignment makes pointer from integer without a cast" no idea why compiler defines it as an int.
Can't declare my function before main as well, it throws this "undefined reference to `free_block'".
#include <stdio.h>
#include <stdlib.h>
struct block{
int num;
};
int main(int argc, char *argv[]) {
struct block *b;
b = free_block();
struct block *free_block(){
struct block *b = NULL;
return b;
}
return 0;
}
Thank you
Yea, my fault I know not too much about c syntax and had no idea about nested functions, soz.
But what could be wrong in this case:
I am trying to make my own memory allocator without using malloc or calloc functions. In my code I have the same Warning on the line with pointer = free_space_get(size);, here I have no more nested func(), my methods defined before main(), but still have no idea do I have to declare my functions or no, coz in the answer given to me it worked fine as soon as functions were defined before the main().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct header{
size_t size;
struct header *next;
unsigned int free;
};
void *m_alloc(size_t size){
size_t total_size;
void *block;
struct header *pointer;
if(!size)
return NULL;
pointer = free_space_get(size);
if(pointer){
pointer->free = 0;
return (void*)(pointer + 1);
}
}
struct header *get_free_space(size_t size){
struct header *b = NULL;
return b;
}
int main() {
return 0;
}
Your code can be re-written as
#include <stdio.h>
#include <stdlib.h>
struct block{
int num;
};
struct block *free_block(){
struct block *b = NULL;
return b;
}
int main(int argc, char *argv[]) {
struct block *b;
b = free_block();
if(b == NULL) // Checking whether pointer is returned
printf("\n Recieved NULL \n");
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 just wrote some C code:
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef struct {
void **data;
time_t lastModified;
} container;
container *container_init() {
container *c = malloc(sizeof(container));
void *data = NULL;
c->data = &data;
c->lastModified = time(NULL);
return c;
}
void *container_getData(container *c) {
void **containerData = c->data;
return *containerData;
}
// only pass manually allocated data that can be free()'d!
void container_setData(container *c, void *data) {
free(container_getData(c));
c->data = &data;
}
void container_free(container *c) {
free(container_getData(c)); // <--- THIS LINE
free(c);
}
int main(int argc, const char *argv[]) {
for (int i = 0; i < 100000000; i++) {
char *data = strdup("Hi, I don't understand pointers!");
container *c = container_init();
container_setData(c, data);
container_free(c);
}
}
My logic was the following: When I call container_setData(), the old data is free()'d and a pointer to the new data is stored. That new data will have to be released at some point. That happens for the last time during the call to container_free().
I have marked a line in the container_free() function. I would have sworn I'd need that line in order to prevent a memory leak. However, I can't use the line ("object beeing freed was not allocated") and there's no memory leak if I delete it. How does the string from my loop ever get released?!
Could someone explain where the error is?
c->data = &data;
stores the address of the pointer data (the argument to your function), not the actual pointer. I.e., you're storing a pointer to a temporary.
You could have built the container structure with just a void *data member.
To explain larsmans answer with code make these changes:
typedef struct {
void *data;
time_t lastModified;
} container;
void *container_getData(container *c) {
return c->data;
}
void container_setData(container *c, void *data) {
free(c->data);
c->data = data;
}
void container_free(container *c) {
free(c->data);
free(c);
}
And other changes too -- this just gets you on the right track.
How can I allocate memory for a struct pointer and assign value to it's member in a subfunction?
The following code will compile but not execute:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _struct {char *str;};
void allocate_and_initialize(struct _struct *s)
{
s = calloc(sizeof(struct _struct), 1);
s->str = calloc(sizeof(char), 12);
strcpy(s->str, "hello world");
}
int main(void)
{
struct _struct *s;
allocate_and_initialize(s);
printf("%s\n", s->str);
return 0;
}
You are passing s by value. The value of s is unchanged in main after the call to allocate_and_initialize
To fix this you must somehow ensure that the s in main points to the memory chunk allocated by the function. This can be done by passing the address of s to the function:
// s is now pointer to a pointer to struct.
void allocate_and_initialize(struct _struct **s)
{
*s = calloc(sizeof(struct _struct), 1);
(*s)->str = calloc(sizeof(char), 12);
strcpy((*s)->str, "hello world");
}
int main(void)
{
struct _struct *s = NULL; // good practice to make it null ptr.
allocate_and_initialize(&s); // pass address of s.
printf("%s\n", s->str);
return 0;
}
Alternatively you can return the address of the chunk allocated in the function back and assign it to s in main as suggested in other answer.
In your example:
void allocate_and_initialize(struct _struct *s)
{
s = calloc(sizeof(struct _struct), 1);
s->str = calloc(sizeof(char), 12);
strcpy(s->str, "hello world");
}
Assigning to s here doesn't change s in the caller. Why not return it instead?
struct _struct *allocate_and_initialize(void) {
struct _struct *s;
s = calloc(sizeof *s, 1);
s->str = calloc(1, 12); /* sizeof(char) is always 1 */
strcpy(s->str, "hello world");
return s;
}
and use it thus:
struct _struct *s;
s = allocate_and_initialize();
/* use s... */
free(s); /* don't forget to free the memory when you're done */
you must change your code like that:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _struct {char *str;};
void allocate_and_initialize(struct _struct **s)
{
*s = (_struct*)calloc(sizeof(struct _struct), 1);
(*s)->str = (char*)calloc(sizeof(char), 12);
strcpy((*s)->str, "hello world");
}
int main(void)
{
struct _struct *s;
allocate_and_initialize(&s);
printf("%s\n", s->str);
return 0;
}
The reason is, that you change the adress of the pointer, but not the "content" of the pointer. So, if you code in c, you have to use a "double" pointer. If you code in c++ you can use a reference.
You can create struct object then pass its address to subfunction, then assign values in subfunction by creating pointer. The exact code is,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _struct {char *str;};
void allocate_and_initialize(struct _struct *s)
{
s -> str = malloc(12);
strcpy(s->str, "hello world");
}
void main(void)
{
struct _struct _struct;
allocate_and_initialize(&_struct);
printf("%s\n", _struct.str);
}