C newbie malloc question - c

Why doesn't this print 5?
void writeValue(int* value) {
value = malloc(sizeof(int));
*value = 5;
}
int main(int argc, char * argv) {
int* value = NULL;
writeValue(value);
printf("value = %d\n", *value); // error trying to access 0x00000000
}
and how can I modify this so it would work while still using a pointer as an argument to writeValue?

Your pointer (int *value) is a value. If you want to keep the above behavior, you need a pointer to a pointer.
void writeValue(int** value) {
*value = malloc(sizeof(int));
**value = 5;
}
int main(int argc, char * argv) {
int *value = NULL;
writeValue(&value); // Address of the pointer value, creates int**
printf("value = %d\n", *value); // prints 5
}

There are 2 bugs, from what I see:
1) If you want to change the value of your pointer you need to pass a pointer to the pointer to your function int **value.
2) If you want to print the value of the pointer in your main, you need to defreference it, *value.

call malloc before calling writevalue, not inside it (thus you'll get the added benefit to be able to free it).
Your program doesn't print 5, but also has a memory leak by losing address of allocated bloc.
The reason as also explained by others is that the parameter int * value is a copy of int * valuein main. You can think of it as a local variable of the function. You can only access to the place it is pointing to. When you modify value in the function the other value in main is not changed.
void writeValue(int* value) {
*value = 5;
}
int main(int argc, char * argv) {
int* value = NULL;
value = malloc(sizeof(int));
writeValue(value);
printf("value = %d\n", *value);
free(value);
}

Related

How to fill an array of structs in a function [duplicate]

This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 4 years ago.
I'm trying to create an array of a structure in an external function "add", and print it's fields, but when I get back to the main function "arr" it is still NULL.
I'm confused because I've been creating arrays in external functions many times and it worked.. probably this time the dynamic memory allocation is messing the things up. Can I please get an advice on this matter?
Thanks!
typedef struct {
char* id;
char gender;
char *name;
}Member;
void add(Member arr[], int size);
void print(Member arr[], int *size);
int main()
{
char temp[100];
int size=0;
Member *arr = NULL;
Member *data = (Member*)malloc(sizeof(Member));
//scan fields
gets(temp);
data->id = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->id, temp);
gets(temp);
data->gender = temp;
gets(temp);
data->name = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->name, temp);
add(data, &arr, &size);
print(arr, &size);
return 0;
}
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
void print(Member arr[], int *size)
{
for (int i = 0;i < *size;i++)
{
puts(arr->id);
puts(arr->gender);
puts(arr->name);
}
}
Imagine code like this:
#include <stdio.h>
void f(int i){
i++;
}
int main(){
int i = 3;
f(3);
printf("%d\n", i);
}
We all know that f() incremented its local copy of i, not the variable that was passed into f() to initially set that value. With that having been said, let's take another look at your add():
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
When arr is passed into the function, it contains a memory address of the current arr, which starts as NULL. But just like when we change the local value of i in f() above, setting arr to a new value within add() only changes the local value; it does not change main()'s arr.
We also know that if we pass a function an address of data we want it to change, the function can then change the data at that address and the data at that address will reflect the change in the calling function:
#include <stdio.h>
void f(int * i){
*i = *i + 1;
}
int main(){
int i = 3;
f(&i);
printf("%d\n", i);
}
The same logic applies ( though it gets more confusing) when you want to change a pointer's value; send that pointer's address! Let's start with a very simple case:
#include <stdio.h>
#include <stdlib.h>
void f(int** i){
*i = (int*)malloc(sizeof(int));
**i = 99;
}
int main(){
int *i = NULL;
f(&i);
printf("%d\n", *i);
}
Here we create a pointer to an int in main, and initialize it to NULL. Then we send the address of that pointer (that is, the address we stored the NULL) to f(), which (like in your program) allocates some memory and puts the address of the newly allocated pointer _at the address of main's i. Now, the data stored at &i has changed, and dereferencing i from main() will dereference the newly allocated address.
In your code, just as in mine, you'll have to change the way you're passing arr to add() as well as how you interact with it - an exercise you'll get the most out of thinking through yourself. But in short, something like this should get you started:
pass add arr's address, not the address it stores.
Store new address of reallocated memory back to the same address, that is, &arr
make sure to update add() to dereference the pointer to a pointer twice to set the member at the address stored at the address &arr.

Where should I use a type char ** in some case as the input parameter?

There is some code piece right here below:
main ()
{
char in[8];
char out[255];
iconv_t cd;
cd = iconv_open("gb18030", "utf-8");
...
char *p_in = in;
char *p_out = out;
size_t inlen = strlen(in);
size_t outlen = sizeof(out);
if (iconv(cd, &p_in, &inlen, &p_out, &outlen) < 0)
{
...
return -1
}
...
return 0;
}
I can't totally understand the 2nd and 3rd parameters of the call to iconv. Why should that be ** pointer not the * pointer as the input? Can anyone explain the cases in C when the ** pointer should be used?
Pointer to pointer is used where the passed pointer is need to be modified in the called function and that modification need to be seen in the caller function. This is required because in C arguments are passed by value. So, when an argument is passed to a function then it simply copied to the function's parameter and created a local copy having block scope. Any change to that variable will not be seen in the argument that has been passed.
void foo(in x){
x = 10;
}
int main(void){
int x = 5;
foo(x)
printf("%d\n", x); // x will be 5
}
Same happens with pointers
void bar(char *p){
p = "foobar";
}
int main(void){
char *p = NULL;
bar(p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Using a pointer to pointer will do the desired job (pointing p to the string "foobar"
void bar(char **p){
*p = "foobar";
}
int main(void){
char *p = NULL;
bar(&p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Another use is when an array of string is need to passed to a function. Like
int main(int argc, char **argv)
or
void print_fruits(char **fruits, size_t len){
for(int i = 0; i < len; i++)
printf("%s\n", fruits[i]);
}
int main(void){
char *fruits[5] = {"Apple", "Banana", "Cherry", "Kiwi", "Orange"};
print_fruits(fruits, sizeof(fruits)/sizeof(fruits[0]));
}
Note that in function call print_fruits, fruits in the argument list will decay to pointer to its first element and the expression fruits will become of type char ** after the conversion.

C - assigning a true int value to void pointer instead of address/pointer value?

I'm having to deal with a generalised linked list so I cannot just turn the data format from a void * to an int.
Miniscule version:
int main(int argc, char **argv) {
void *data;
int i = 100;
*((int*)data) = i;
printf("%d", (int)data);
return 0;
}
Keeps printing an address. Likewise, data = &i also returns an address. data = i just results in an error. I've tried all that I can and just cannot insert the value i into data.
You need to make data point to a valid memory address first:
int main(int argc, char **argv) {
void *data = malloc(sizeof (int));
int i = 100;
*((int*)data) = i;
printf("%d", *((int*)data));
return 0;
}
Without that malloc(), double undefined behaviour(accessing an uninitialised object && writing data to a random address) will be invoked.
Also, change (int)data to *((int*)data) in your printf() statement. If sizeof (int) > sizeof (void *), data will be truncated when being cast.
If you need to use a void * as a generalised container.
Got two options for integer or other data types
void * data = malloc(sizeof(DATATYPE)); // Datatype can be int in this case
Then
*((int *)data) = SOME VALUE;
Then free it at some point
Otherwise one can usually assume an internet "fits" into a void *.
I would not go down this avenue.

Pointer manipulation inside function

Let's say I have a pointer pointing to memory
0x10000000
I want to add to it so it traverses down memory, for example:
0x10000000 + 5 = 0x10000005
How would I do this inside a function? How would I pass in the address that the pointer points to, and inside the function add 5 to it, then after the function's complete, I can use that value?
You have two options:
The function can return the updated pointer.
char *f(char *ptr) {
ptr += 5;
return ptr;
}
The caller then does:
char *p = some_initialization;
p = f(p);
The function argument can be a pointer to a pointer, which it indirects through:
void f(char **ptr_ptr) {
*ptr += 5;
}
The caller then does:
char *p = some_initialization;
f(&p);
Basically, like what everyone else as said you have to pass the pointer by reference(that is a pointer to a pointer aka double pointer) to the function.
#include<stdio.h>
void IncrementAddress(void **addr)
{
int offset=5;//give what ever value you want
*addr = *addr + offset;
printf("%d\n",*addr);
}
int main()
{
char x;// or any other data type like int x or float x etc.
void *ptr=NULL;
ptr = &x;
printf("%d\n",ptr);
IncrementAddress(&ptr);
printf("%d\n",ptr);
return 0;
}

Passing char pointer in C

Okay so I am trying to pass a char pointer to another function. I can do this with an array of a char but cannot do with a char pointer. Problem is I don't know the size of it so I cannot declare anything about the size within the main() function.
#include <stdio.h>
void ptrch ( char * point) {
point = "asd";
}
int main() {
char * point;
ptrch(point);
printf("%s\n", point);
return 0;
}
This does not work however, these two works:
1)
#include <stdio.h>
int main() {
char * point;
point = "asd";
printf("%s\n", point);
return 0;
}
2)
#include <stdio.h>
#include <string.h>
void ptrch ( char * point) {
strcpy(point, "asd");
}
int main() {
char point[10];
ptrch(point);
printf("%s\n", point);
return 0;
}
So I am trying to understand the reason and a possible solution for my problem
This should work since pointer to the char pointer is passed. Therefore any changes to the pointer will be seen outside thereafter.
void ptrch ( char ** point) {
*point = "asd";
}
int main() {
char * point;
ptrch(&point);
printf("%s\n", point);
return 0;
}
void ptrch ( char * point) {
point = "asd";
}
Your pointer is passed by value, and this code copies, then overwrites the copy. So the original pointer is untouched.
P.S. Point to be noted that when you do point = "blah" you are creating a string literal, and any attempt to modify is Undefined behaviour, so it should really be const char *
To Fix - pass a pointer to a pointer as #Hassan TM does, or return the pointer as below.
const char *ptrch () {
return "asd";
}
...
const char* point = ptrch();
Here:
int main() {
char * point;
ptrch(point);
You're passing point by value. Then, ptrch sets its own local copy of point to point to "asd", leaving the point in main untouched.
A solution would be to pass a pointer to main's point:
void ptrch(char **pp) { *pp = "asd"; return; }
If you change the value of the pointer in a function, it will remain changed only in that one function call.
Don't mess your head with pointers and try:
void func(int i){
i=5;
}
int main(){
int i=0;
func(i);
printf("%d\n",i);
return 0;
}
The same with your pointer. You do not change the address it points to.
If you assign to a variable passed by value, the variable outside the function will remain unchanged.
You could pass it by a pointer (to pointer) and change it by dereferrencing it and it's the same with an int - in this case, it doesn't matter if the type is int or char * .
first declare funtion......like this
#include<stdio.h>
void function_call(char s)
next write main code.....
void main()
{
void (*pnt)(char); // pointer function declaration....
pnt=&function_call; // assign address of function
(*pnt)('b'); // call funtion....
}

Resources