Returning pointers back to itself - c

My coding assignments came with it's header file, meaning we need to use the same data types, and not vary anything.
There is a lot of pointers, (mainly a lot of void *). Meaning things are confusing, more than difficult.
we have to do a separate function, just to increment the value referenced by a pointer. But given the nature of program, I don't want to constantly make new pointers.
The code is as follows:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void* intal_create(const char* );
void* intal_increment(void* );
void *intal_create(const char* str)
{
int a;
a=atoi(str);
return &a;
}
void *intal_increment(void *intal)
{
int *a= (int *)intal;//new pointer;
++*a;
//value referenced has been incremented;
*(int *)intal=*a;
return intal;
}
int main()
{
int * x;// void * return a pointer, need a pointert to int to pick it up
char *dummy;
gets(dummy);
x=(int *)intal_create(dummy);
printf("integer return is %d\n",*(int *)x);
printf("address stored is %p\n",(int *)x);
x=(int *)intal_increment(x);
printf("integer return is %d\n",*(int *)x);
printf("address stored is %p\n",(int *)x);
}
I wanted x to be the parameter called, and also for it to store the return value. The printf address is merely for my understanding.
The segmentation faults never end, and from my understanding, I'm just returning a pointer and asking a pointer to stop the return pointer

By incorporating all the comments. Mainly allocating memory to dummy before passing it gets() function and allocating memory in heap for the return pointer of intal_create.These two fixes solve the issue. Have a look at the following code for reference.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void* intal_create(const char* );
void* intal_increment(void* );
void *intal_create(const char* str)
{
int *a = (int *)malloc(sizeof(int));
*a = atoi(str);
return a;
}
void *intal_increment(void *intal)
{
//Here i am not allocating
int *a = (int *)intal;//new pointer;
(*a)++;
return intal;
}
int main()
{
int * x;// void * return a pointer, need a pointert to int to pick it up
char dummy[20] = {0};
fgets(dummy,5,stdin);
x = (int *)intal_create(dummy);
printf("integer return is %d\n",*x);
printf("address stored is %p\n",(void*)x);
x=(int *)intal_increment(x);
printf("integer return is %d\n",*x);
printf("address stored is %p\n",(void *)x);
//Make sure you deallocate the memory allocated in the intal_create function.
free(x);
}

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.

C pointer lost after multiple assignments

I am new to C programming and having some issues with the pointers in the following code. I am using the C89 standard.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * b(char *p) {
char *z;
z = p;
printf("b(): %s\n", z);
return z;
}
void a(char *p, char *q) {
q = b(p);
printf("a(): %s\n", q);
}
void main(void) {
char *p = (char *) malloc(15);
char *q;
strcpy(p, "This is a test");
a(p,q);
printf("main(): %s\n", q);
free(p);
}
For some reason, my printf function is printing nothing in the main() function. The printf calls in both of the functions a() and b() are working. I am not sure why my pointer "q" is lost in the main function. I even tried allocation dynamic memory to "q" in main() function but still no results.
q in main() is uninitialized. You probably assume that q is changed after a(p,q), but as that pointer is passed by value (as everything in C), after returning from a, any changes done to q are discarded (they were local to a)
To solve this, while preserving most of your function signatures, you would have to add another level of pointers
In following code, p and q in a are local to a, but you are not directly changing any of them, insted, you are modifying value, that is pointed at by q (that value is of type *char, so another ponter, easy to get lost)
void a(char *p, char **q) {
*q = b(p);
printf("a(): %s\n", q);
}
void main(void) {
...
a(p,&q);
printf("main(): %s\n", *q);
....
}
Or simply return that pointer, and assign to q in main (as you have done in b)
To better understand why this is happening, consider this simpler example:
void foo(int a) {
print("value is %d\n", a);
a = 42; // modifies only a local copy of passed parameter a
print("modified value is %d\n", a);
}
int main() {
int a = 0
printf("initial value is %d\n", a);
foo(a);
printf("value after returning is (still) %d\n, a");
}

Swap without worrying about the data type

Is that implementation valid and safe to swap two array or variable without worrying about their data type? Or should I use a function pointer?.
This type of code is focusing about using a good implementation of void pointers to swap without worring about the data type.
#include <stdio.h>
#include <string.h>
void swap(void *, void *, int);
int main(void) {
char a[] = "home";
char b[] = "door";
printf("%s %s\n", a, b);
swap(&a, &b, sizeof(a));
printf("%s %s \n", a, b);
return 0;
}
void swap( void *a, void *b, int siz){
char buff[siz]; // I voluntarily omitted dynamic allocation.
memcpy(buff,a,siz);
memcpy(a,b,siz);
memcpy(b,buff,siz);
}
In C, this approach is usually okay (and it's used by standard functions such as qsort()). The contra-indications that indicate you can't use this are when there are any pointers to your objects or their members. Also, take care in multi-threaded code.
Note that in C++, we have std::swap() which will respect user-defined copy/move constructors; copying a C++ object by simply copying its memory is not (in general) valid.
This swap() function is as good/bad as the memcpy() it uses.
If the data structures are just some data structures (of int, float, etc.), it works like a charm.
If you pass two pointers to different structures, all hell will break loose. Offending code:
Foo* myFoo = ...;
Bar* myBar = ...;
swap(myFoo, myBar, sizeof(*myFoo));
Note that your compiler won't complain on this as both pointer types are implicitly convertible to the void*s that swap() expects. But the result of compilation will be bullshit.
If the structure you copy contains a pointer into itself, that pointer will point into the other object after the swap(). The following struct would be an offender of this:
typedef struct {
char* data;
size_t length, allocatedLength;
char shortStringBuffer[32];
} myString;
The idea behind this is, that short strings will be stored in the shortStringBuffer, and data will point to the shortStringBuffer. Strings longer than 31 characters will be stored in dynamically allocated memory, and again be accessible via the data member. It is left as an exercise to the reader to figure out, what precisely happens when you try to copy this thing with a memcpy().
What you must understand, is that memcpy() really only copies bytes, and some data is not invariant to where it is stored. So, each and every use of memcpy() must be accompanied with a proof that it does the correct thing in this particular case. Well, it should. I've never seen such a proof in a comment for some reason...
You can just swap their addresses without further operation to swap two variables/arrays. I tried this and it works:
#include <stdio.h>
int main(void) {
char *a = "home";
char *b = "root";
char *c = a, *d = b;
printf("%s %s\n", a, b);
a = d;
b = c;
printf("%s %s \n", a, b);
return 0;
}
Outputs:
home root
root home
https://ideone.com/MMCOpf
It is safe to use generic pointers to swap, however you must make sure you get the sizes right, and that you don't overflow any array or object:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int swap(void *a, void *b,
size_t a_size, size_t b_size);
int main(void) {
char a[] = "home";
char b[] = "door";
printf("%s %s\n", a, b);
int ret = swap(a, b, sizeof(a), sizeof(b));
if(ret) {
printf("%s %s \n", a, b);
}
return ret;
}
int swap(void *a, void *b,
size_t a_size, size_t b_size)
{
if (b_size != a_size ) {
return 0;
}
void *tmp = malloc(a_size);
if(!tmp) {
return 0;
}
memcpy(tmp, a, a_size);
memcpy(a, b, b_size);
memcpy(b, tmp, a_size);
free(tmp); // tmp no longer needed.
return 1;
}
I solved this by C, code for your reference.
Using uint16_t is neccessary to hold the carry bit when two large uint8_t variables plus.
int main(){
uint8_t tmp[9] = {0x0};
for (int i=9-1; i>=0 ; i--) *(tmp+i) = 0xff-i;
uint16_t tmp2[9];
for (int i=0; i<9; i++) tmp2[i] = tmp[i];
byte_swap_uint8_data(tmp2, 9);
}
void byte_swap_uint8_data(uint16_t* data, int w) {
if (w < 2) return;
for (int i=0; i<w/2; i++) {
data[i] += data[w-1-i];
data[w-1-i] = data[i] - data[w-1-i];
data[i] = data[i] - data[w-1-i];
}
}

Returning a value from a thread in C

Hello i am having a hard time understanding how a value is returned from a thread in c. I have this working example:
#define NTHREADS 4
void *neg (void * param) {
int *l;
l=(int *) param;
int *r=(int *)malloc(sizeof(int));
*r=-*l;
return ((void *) r);
}
int main (int argc, char *argv[]) {
pthread_t threads[NTHREADS];
int arg[NTHREADS];
int err;
for(long i=0;i<NTHREADS;i++) {
arg[i]=i;
err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i]));
if(err!=0)
error(err,"pthread_create");
}
for(int i=0;i<NTHREADS;i++) {
int *r;
err=pthread_join(threads[i],(void **)&r);
printf("Resultat[%d]=%d\n",i,*r);
free(r);
if(err!=0)
error(err,"pthread_join");
}
return(EXIT_SUCCESS);
}
What i find hard to understand is the following:
the function neg returns a pointer * r casted in (void *) pointing to a value in the heap. Thus returning an adress to the heap basically. Then in pthread_join we get that return value by doing &r (which by itself seems illogical? grab the adress of an adress?) then casting to a pointer of a pointer? Why do we do that?
Thanks for the help!
Consider this code, which is perfectly valid and prints "5 5 5 5".
int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
printf("%d %d %d %d\n", x, *p, **pp, ***ppp);
return 0;
C allows you to have any depth of pointers, initialized with a corresponding number of address-of operators. In your example, you allocated an int * and the function must return a void **, so you have to dereference the result twice and cast it, which you accomplished by casting the int *.
So,"grab the adress of an adress?" Yup! Well, the address of a pointer, which may hold the address of an int, or another pointer.
Then in pthread_join we get that return value by doing &r (which by
itself seems illogical? grab the adress of an adress?) then casting to
a pointer of a pointer? Why do we do that?
First thing you need to understand is that the thread function(s) do not return the value directly; they send the value to the pthreads library using pthread_exit() or returning a value (as in your example) and
it's retrieved with a call to pthread_join() (by using the thread identifier). Since the return value is a pointer, you have to
pass a pointer to pointer to retrieve it from pthread_join() function.
For the understanding purposes, consider this pseudo code:
/* thread */
void *neg(void *arg)
{
return ptr; // let's say "ptr" is stored in the library as "retval_thread_id"
}
int pthread_joing(pthread_t thread_id, void **retval)
{
*retval = retval_thread_id;
}
int main(void)
{
rc = pthread_join(threads[i],(void **)&r);
}
So, how can you retrieve the pointer retval_thread_id from pthread_join() without using a pointer to pointer?
This is nothing different than passing a ptr-to-ptr to a function and the function stores at the pointee of the passed pointer:
void func(int **p)
{
*p = malloc(10 * sizeof *p);
}
int main(void)
{
int *p;
func(&p);
}
By the way , all the casts you do (except the one in the call to pthread_join() -- You wouldn't this either if you declared r as void *r;.) are unnecessary. A void pointer can be assigned to any other data pointer in C without a cast.

Pointer question

Okay I go through 2 layers of functions fun1 calls func2 calls func3 . I pass a pointer all the way down using basically int *ptr, at the lowest "level" of the call stack I also have another function that dynamically allocates memory for an int array. At the top level (func1 level) I always get null back for the passed pointer. I have traced down to func3 and the allocated memory is being filled with values, but as the call stack unwinds func3 -> func2 suddenly the pointer just goes away (0x0000_0000)? I don't understand at func3 level I basically say ptr = allocate_ptr_array, but from that return it goes to NULL! Even though I didn't free the memory, what in the world is going on? I know my question is confusing. I have watched this happen in the debugger though
The pointer is basically passed by value. You need to pass pointer to pointer (int **p) to get the memory allocated back in outer function.
function1(int *p)
{
p = //allocate memory using malloc
}
function2(int **p)
{
*p = //allocate memory using malloc
}
function3()
{
int *p;
function1(p);
// in this case pointer is passed by value.
//The memory allocated will not be available in p after the function call function1.
int **p;
function2(&p);
//in this case pointer to pointer p has been passed.
// P will have the memory allocated even after
//the function call function1
}
}
To illuminate aJ's (completely correct) answer with some code:
void func1(void)
{
int *int_array;
func2(&int_array);
/* Some stuff using int_array[0] etc */
/* ... */
free(int_array);
}
void func2(int **a)
{
/* ... stuff ... */
func3(a);
/* .... stuff ... */
}
void func3(int **a)
{
(*a) = malloc(N * sizeof **a);
}
Here is a good example for future reference bye other people. It makes sense after implementation and thanks to these guys.
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
void func3(int **ptr)
{
int i;
(*ptr) = (int *)malloc(25*sizeof(int));
for (i=0; i < 25; i++) (**ptr) = i;
printf("func3: %d\n",ptr);
}
void func2(int **ptr)
{
func3(ptr);
printf("func2: %d\n", ptr);
}
void func1(void)
{
int *ptr;
printf("ptr before: %d\n", ptr);
func2(&ptr);
printf("ptr after: %d\n", ptr);
}
void func4(int **ptr)
{
static int stuff[25];
printf("stuff: %d\n",stuff);
*ptr = stuff;
}
int main(void)
{
int *painter;
func1();
func4(&painter);
printf("painter: %d\n", painter);
return 0;
}

Resources