Changing variables from outside - c

In main() function I initialize a couple of variables (int and int* array). Then I print something out and read them from the console scanf.
I want to place this functionality into some external function so that the main will look like this:
int main()
{
int n = 0, x = 0;
int *arr = NULL;
load(&n, &x, &arr);
}
After load() function call I want the variables to be exactly as they were set inside of the load() function. How can I do this?
And second question, just out of curiosity:
/**
* Description of the function
*
* #param int n Foo
* #param int x Bar
* #param int *arr Does something
*/
void load(int n, int x, int *arr)
{
// something
}
Is this documentation useful in C coding, and is it a good practice?

You are passing address of two int and one pointer(third argument), you should receive first two arguments in pointer(one *) to int and third argument in pointer to pointer(two **) of int:
void load(int* n, int* x, int **arr){
// ^ ^ one* ^ two **
*n = 10;
*x = 9;
}
In load function you can assign values to *n and *x because both points to valid memory addresses but you can't do **arr = 10 simply because arr doesn't points to any memory (points to NULL) so first you have to first allocate memory for *arr, do like:
void load(int* n, int* x, int **arr){
*n = 10;
*x = 9;
*arr = malloc(sizeof(int));
**arr = 10;
}
Is this documentation useful in C coding, and is it a good practice?
Yes
but Sometimes I documents my function arguments like in following ways:
void load(int n, // is a Foo
int x, // is a Bar
int **arr){ // do some thing
// something
}
A reference: for document practice
Edit As you are commenting, do like below I am writing, it will not give any error/because of malloc().
#include<stdio.h>
#include<stdlib.h>
void load(int* n, int* x, int **arr){
*n = 10;
*x = 9;
*arr = malloc(sizeof(int));
**arr = 10;
printf("\n Enter Three numbers: ");
scanf("%d%d%d",n,x,*arr);
}
int main(){
int n = 0, x = 0;
int *arr = NULL;
load(&n, &x, &arr);
printf("%d %d %d\n", n, x, *arr);
free(arr);
return EXIT_SUCCESS;
}
Compile and run like:
~$ gcc ss.c -Wall
:~$ ./a.out
Enter Three numbers: 12 13 -3
12 13 -3
As Commented by OP:
"Invalid convertion from void* to int*" when I change this to arr = malloc(sizeof(int)(*n));
syntax of malloc():
void *malloc(size_t size);
malloc() returns void* and *arr type is int* that is the reason compiler messages because of different types : "Invalid convertion from void* to int*"
But I avoid casting when malloc(), since: Do I cast the result of malloc? (read Unwind's answer)

Related

C iki boyutlu dizi Malloc

I don't know where I'm wrong and I get segmentation fault error. Can you help?
My Code;
#include <stdio.h>
#include <stdlib.h>
void do_array(int x, int y, int **arr){
arr=(int **)malloc(sizeof(int)*x);
for (int i=0;i<y;i++){
*(arr+i)=(int *)malloc(sizeof(int)*y);
}
}
int main(){
int **p;
do_array(5,2,p);
for (int i=0;i<5;i++){
for (int j=0;j<2;j++){
*(*(p+i)+j)=i;
}
}
for (int i=0;i<5;i++){
for (int j=0;j<2;j++){
printf("%d\n",*(*(p+i)+j));
}
}
return 0;
}
!!! I want to do is create a dynamic 2D array
The formal argument arr in the function is a separate object from the actual argument p in main - any changes to arr are not applied to p, so p is never set to point to the memory you just allocated.
What you will have to do is pass a pointer to p:
void doArr(int x, int y, int ***arr){
*arr=(int **)malloc(sizeof(int *)*x); // note type of sizeof - you're allocating an array of int *, not int
for (int i=0;i<y;i++){
*(*arr+i)=(int *)malloc(sizeof(int)*y);
}
}
...
doArr( 5, 2, &p );
Or, return arr and assign the result of doArr to p:
int **p = doArr( int x, int y )
{
int **arr = malloc(...);
...
return arr;
}
p = doArr( 5, 2 );
As Emanuel P notes, do is a keyword, so you can't use it as a function name.
A couple of style notes:
Since C89, malloc returns void * and does not require an explicit cast, and many of us will recommend against using it. It just adds visual noise and creates an extra maintenance burden.
Similarly, I often recommend that the operand of sizeof be your target expression, not a type name. Again, this eases your maintenance headaches if you change the type of the destination pointer.
Use array notation instead of pointer arithmetic where possible. It's easier to read and follow, and you're less likely to make a mistake.
Finally, always check the result of a malloc, calloc, or realloc call.
I'd rewrite your doArr function as follows:
void doArr(int x, int y, int ***arr)
{
*arr = malloc( sizeof **arr * x );
if ( *arr )
{
for ( int i = 0; i < y; i++ )
{
(*arr)[i] = malloc( sizeof *(*arr)[i] * y );
}
}
}
and call it as
doArr( 5, 2, &p );
int main(){
int **p /* = NULL */ ; // p is garbage or NULL
do_array(5,2,p); // p is still garbage or NULL
for (int i=0;i<5;i++){
for (int j=0;j<2;j++){
*(*(p+i)+j)=i; // p is still garbage or NULL
I want to do is create a dynamic 2D array
In your code you do not create a 2D array only the array of pointers.
void *doArr(size_t x, size_t y)
{
int (*arr)[x][y] = malloc( sizeof((*arr)[0][0]) * x * y);
return arr;
}

Small generic programming issue in C

So I'm starting to understand the basics of generic programming in C. I'm currently building a program that says if a value occurs or not in a given sequence of number.
I think that the bug occurs in the cmpValues function. Would anyone point it out? (for example, for want=4 and v={1,2,3,4,5}, the program says that want is not in v)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void *search(const void *x, const void *t, int n, int d, int (*cmpValues)(const void *, const void *)){
char *p = (char *)t;
int i;
for(i=0;i<n;++i)
if(cmpValues(x,p+i*d))
return p+i*d;
return NULL;
}
int cmpValues(const void *a, const void *b){
if((char *)a == (char *)b)
return 1;
return 0;
}
int main() {
FILE *f = fopen("datein.txt", "r");
FILE *g = fopen("dateout.txt", "w");
int *v, n, i, want;
fscanf(f, "%d", &n);
v = (int *)malloc(n * sizeof(int));
for(i = 0; i < n; ++i)
fscanf(f, "%d", v + i);
fscanf(f, "%d", &want);
if(search(&want, v, n, sizeof(int), cmpValues))
fprintf(g, "The value %d is found at position %d.\n\n", want, search(&want, v, n, sizeof(int), cmpValues));
else
fprintf(g, "The value does bot occur in the given sequence.\n\n");
return 0;
}
In cmpValues, you are comparing 2 objects pointed by 2 void pointers (i.e. you don't know their type, nor their size). Let's assume we are having ints, and that an int has 4 bytes, which is usually the case.
Just for the sake of it, let's assume that the a pointer has value 0x100 (i.e. points to a int from 0x100 to 0x103, inclusive) and b pointer has a value of 0x104 (i.e. points to the int from 0x104 to 0x107).
Now, you are converting them to char* (char has 1 byte) and compare the value of the pointers. Now, the type of the pointer does not matter in comparisons. In that comparison, you will compare memory addresses (in my example, 0x100 and 0x104). Obviously, the only way the function will return 1 is if the pointers would point to the same variable.
Now, in order to fix it, you should compare the values at the memory addresses pointed by your pointers. However, simply dereferencing the pointers:
*((char *)a) == *((char *)b)
won't be enough, since this would compare just the first byte of a with the first byte of b (under the assumption that char has 1 byte). Also, you can't dereference void*.
So, you need to iterate over your variables and compare them byte by byte (this assumes that you know the size of the data type):
int comp(void *a, void *b, int size) {
// convert a and b to char* (1 byte data type)
char *ca = a;
char *cb = b;
// iterate over size bytes and try to find a difference
for (int i = 0; i < size; i++) {
if (*(ca + i) != *(cb + j)) {
return 0;
}
}
// if no difference has been found, the elements are equal
return 1;
}
side note: you don't need to call cauta twice in main.

C function with pointers work on one computer, and doesn't work on another

#include <stdio.h>
void swap (int *a, int *b)
{
int *tmp;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
}
I'm using codeblocks, and this code won't work, and I don't understand why... On one computer it works perfectly but on the other it won't run at all.
Any help?
Thanks in advance.
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
What you need is a variable tmp to store the value and not a pointer *tmp.
The below code really a poor way of doing this but
int *tmp = malloc(sizeof(int));
*tmp = *a;
*a = *b;
*b = *tmp;
Once done please free the memory using
free(tmp);
Gopi already corrected your code - adding on to the previous answer - i think this is good to know information for a newbie:
Section 4.1 states:
An lvalue (3.10) of a
non-function, non-array type T can be
converted to an rvalue. If T is an
incomplete type, a program that
necessitates this conversion is
ill-formed. If the object to which the
lvalue refers is not an object of type
T and is not an object of a type
derived from T, or if the object is
uninitialized, a program that
necessitates this conversion has
undefined behavior. If T is a
non-class type, the type of the rvalue
is the cv-unqualified version of T.
Otherwise, the type of the rvalue is
T.
When you try to dereference and uninitialized pointer the behavior is undefined. Undefined means anything can happen - there is no guarantee. So you can get different behavior in different environments.
From Wiki Making pointers safer
A pointer which does not have any address assigned to it is called a wild pointer. Any attempt to use such uninitialized pointers can cause unexpected behavior, either because the initial value is not a valid address, or because using it may damage other parts of the program. The result is often a segmentation fault, storage violation or wild branch (if used as a function pointer or branch address).
What you did here:
int *tmp;
*tmp = *a;
is that you created a pointer to int which is not pointing to anything - basically it contains some junk value (could be your pincode even - who knows).
Your mistake was to use uninitialized memory. Always allocate memory to a pointer before using it. Next, don't forget to free the allocated memory after you're done with it.
Also, you should add return 0; at the end of your main() function.
If you don't mind a second opinion, check the below code.
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b)
{
int *tmp = malloc(sizeof(*tmp));
*tmp = *a;
*a = *b;
*b = *tmp;
free(tmp);
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
return 0;
}
If you want to use pointers, although it does not make any sense at all
void swap(int *a, int *b)
{
int tmp[1];
*tmp = *a;
*a = *b;
*b = *tmp;
}
here tmp is not strictly a pointer, but you can use the * indirection operator on it.
Or
void swap(int *a, int *b)
{
int value = *a;
int *tmp = &value;
*tmp = *a;
*a = *b;
*b = *tmp;
}
Or you can use malloc as Gopi already pointed out.
If you want to use pointers, then do use pointers:
#include <stdio.h>
void swap (int ** ppx, int ** ppy)
{
int * p = *ppx;
*ppx = *ppy;
*ppy = p;
}
int main (void)
{
int x = 5;
int y = 7;
int * px = &x;
int * py = &y;
printf ("\nx = %d\ny = %d\n", *px, *py);
swap (&px, &py);
printf ("\nx = %d\ny = %d\n", *px, *py);
return 0;
}
Result:
x = 5
y = 7
x = 7
y = 5

Updating a pointer to a c array from a function

Say I have a function called array_push in c.
void array_push(int *array_pointer, int array_length, int val) {
int i;
int *temp_array = malloc(sizeof(int) * (array_length + 1));
for (i = 0; i < array_length; i++) {
temp_array[i] = *array_pointer;
array_pointer++;
}
temp_array[array_length] = val;
*array_pointer = temp_array;
}
How can I update the pointer *array_pointer so that it points to temp_array and other parts of my program can use the new array? Allowing me to do something like
int t[2] = {0,2};
array_push(t, 2);
/* t should now contain {0,2,3} */
You need to turn array_pointer into a pointer-to-pointer:
void array_push(int **array_pointer, int array_length, int val) {
(note the extra asterisk).
Also, you'll need to change the call site so that t is a pointer, not an array (you can't make an array point someplace else). Finally, to make the caller aware of the new size of the array, array_length also needs to be passed by pointer.
Thus, the overall structure of your code could be something like:
void array_push(int **array_pointer, int *array_length, int val) {
int *temp_array = malloc(sizeof(int) * (*array_length + 1));
memcpy(temp_array, *array_pointer, sizeof(int) * *array_length);
temp_array[(*array_length)++] = val;
free(*array_pointer);
*array_pointer = temp_array;
}
int main() {
int n = ...;
int* t = malloc(sizeof(int) * n);
/* ... */
array_push(&t, &n, 2);
/* ... */
free(t);
}
Note how I've allocated t on the heap, and have freed *array_pointer inside array_push(). With this in mind, much of the array_push()'s logic can be simplified by using realloc():
void array_push(int **array_pointer, int *array_length, int val) {
*array_pointer = realloc(*array_pointer, sizeof(int) * (*array_length + 1));
(*array_pointer)[(*array_length)++] = val;
}
There are two problems here: You seem confused about pass-by-value, but the more significant problem is that you seem confused about pointers. int *array_pointer array_pointer points to an int, not an array. It may be that it points to the first int in an array. On an unrelated note, a "pointer to an int array" looks like: int (*array_pointer)[array_length].
Back to the point: int *array_pointer array_pointer points to an int. In *array_pointer = temp_array;, the expression *array_pointer gives you the object pointed to, which can store an int. temp_array isn't an int value, though.
I can see that you're attempting to work around the issue that changes made to array_pointer aren't visible to the caller, due to the semantics of pass-by-value. Hence, you need to change array_pointer so that it points to an int * that the caller supplies, so that you're modifying the caller's int *, or use the return type to return the new pointer. As it turns out, both of these options solve both of your problems.
PROBLEM 1:
If you want to create or modify an *int array inside of a function, then you need to pass a "pointer to a pointer":
// WRONG:
void array_push(int *array_pointer, int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
*array_pointer = temp_array;
Instead:
// BETTER:
void array_push(int **array_pointer, int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
*array_pointer = temp_array;
Or:
// BETTER YET:
int * array_push(int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
return temp_array;
PROBLEM 2:
If you want to declare a static array like this int t[2] = {0,2};, then you can't arbitrarily change it's size. Here's a good description of "arrays vs pointers":
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1069897882&id=1073086407
One of the first things a new student learns when studying C and C++
is that pointers and arrays are equivalent. This couldn't be further
from the truth...

C: Accessing a pointer from outside a function

I have the following code:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
-1
2088999640
2088857728
If I try printing the first element of the newlist pointer before returning the function (printf("First number found %d\n", *newlist);), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
You need to pass in a pointer to pointer, i.e. int **newlist. Specifically, newlist is being passed into your function by value, so the newlist in main and inside your function are two completely different variables.
There is also a bug in your test for even numbers:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
The newlist you have at the end of the function is not the same as you have when calling the function.
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
You're passing a pointer by value here:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free:
free(evenNums);
In C, everything is passed by value. So you are passing a copy of evenNums to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int** as the third parameter.

Resources