How pass(to function) by value variable size array? - c

First of all I know that array A degrades to pointer when we call function f(int a[]) and f(int *p) is same.
BUT:
1.I really need sending by value all array.
2.I really need that sending size is non const in function (but const size in plase we calling function)
I write some example:
http://ideone.com/ZbW0wT
#include <stdio.h>
#define SZ 15
typedef struct {int a[SZ];} rec;
int main(){
void pa(rec);
int value[SZ] ={9,8,7,6,5,4,3,2,1,0};
pa(*(rec*)value);
printf("%u %u\n",sizeof(rec),sizeof(value));
return 0;
}
void
pa(rec b){
int z;
for(z=0;z<SZ;z++){
printf("array[%2d] is %d\n",z,b.a[z]);
}
}
This code work for const size , but how change so pa would get by value some rec which size depend on passed array?
Update: it must by value sended , but not const sized as in Pascal etc , but in true C way , all pass by value not by pointer on 0 element
and function need universal so user can write func(variablesizeArrayOfT) where arg passed by value.
if possible need standard way (C11 or better C99 or better C89 or better K&R), if cant then gcc
UPD2: http://ideone.com/H4XGqC
#include
typedef struct{
int len;
int a[];
} av;
void f(av a){
while(a.len--){
printf("array[%2d] is %d\n",a.len,a.a[a.len]);
}
}
int main(){
int b[]={3,1,2,3};
int c[]={7,1,2,3,4,5,6,7};
f(*(av*)b);
f(*(av*)c);
return 0;
}
all good by probably bug in alignment so size(3 and 7) is right but value of a[] is not
UPD3 see throw gcc -g -c 2ndSRC.c &&objdump -d -M intel -S 2ndSRC.o
it just send only size (b[0] and c[0]) but not all array

An idiomatic way to have arrays containing data of variable length in C is to use a buffer with a maximum size which is known at compile time, is that what you wanted?
#include <stdio.h>
#define MAX_SIZE 15
typedef struct {
int arr[MAX_SIZE];
size_t arr_len;
} rec_t;
void pa(rec_t rec){
for(int z=0; z<rec.arr_len; z++){
printf("array[%2d] is %d\n", z, rec.arr[z]);
}
}
int main(void){
rec_t rec ={
.arr = {9,8,7,6,5,4,3,2,1,0},
.arr_len = 10
};
pa(rec);
}

Related

Passing an array from a method in file 1 to a method in file 2 without using a extra parameter in a method

I am getting all Zeroes in global_array_of_file2.Idea is to get the updated values from file1.c
========================file1.c===========================
#include <stdio.h>
#include <string.h>
int global_array_of_file1[10];
void func1(int a1,int b)
{
int array1_of_func1[10] = {0};
int a;
array1_of_func1[5] = 23;
array1_of_func1[6] = 34;
memcpy(global_array_of_file1,array1_of_func1,10*sizeof(int));
for (a = 0; a < 9; a++)
{
printf("from func_1 : global_array = %d \n " , global_array_of_file1[a]);
}
}
void init_pointer(int *tmp)
{
tmp = global_array_of_file1;
}
~
==========================file2.c======================
#include<stdio.h>
#include "file1.h"
int global_array_of_file2[10] = {0};
int main()
{
int i;
init_pointer(global_array_of_file2);
func1(3,4);
for(i = 0; i < 9 ; i++)
{
printf("global_array_of_file2 = %d \n" , global_array_of_file2[i]);
}
return 0;
}
========================file1.h===========================
void init_pointer(int *tmp);
void func1(int a,int b);
There are two issues here:
First issue is:
the code for init_pointer does nothing:
void init_pointer(int *tmp)
{
tmp = global_array_of_file1;
}
as tmp variable is a copy of the input variable (called by value), it does nothing.
To have it work correctly it should be something like this:
void init_pointer(int **tmp)
{
*tmp = global_array_of_file1;
}
However, as the global_array_of_file2 is declared as array, it is actually a static pointer which cannot be changed, so you cannot modify its value using statement like **tmp= global_array_of_file1.
Therefor to make it work, you should call memcpy within the init pointer method:
like this:
void init_pointer(int *tmp)
{
memcpy( tmp, global_array_of_file1, 10 * sizeof(int) );
}
The second issue, is that the code at main, first call the init_pointer (which does nothing), then it calls 'func1' which initialize the array. the order shall be the opposite. first call func1 to set the array with the appropriate values, then call the init_array method to copy this information to global array 2.
so instead of
init_pointer(global_array_of_file2);
func1(3,4);
it shall be
func1(3,4);
init_pointer(global_array_of_file2);
This is all if you want to have a copy of the global_array_file1 at file2.
If you want, you can have the same array shared between files, to do so:
at file1.h declare the array as extern:
extern int global_array_of_file1[10];
Then you can simply use it at file2.c which include file1.h
Ok I think this can be fixed easily by doing the below :
declare extern int global_array_of_file1[10] in file1.c
define int global_array_of_file1[10] = {0}; in file2.c
I then dont even need to initialize the pointer from file2.c ( no need to call init_pointer) and extra RAM too will be saved :) !
The memcpy is wrong. You just copy 10 bytes.
An int is usually 4 Bytes long (32 bit), thus you only copy parts of the array, namely the first ten bytes, thus you copy just the ints with index 0,1,2 and half of 4.
You need to copy 10 * sizeof(int)

Adding pointers to an array of pointers

I'm trying to make a program that for a given int value keeps the amount of dividers:
int amount_of_dividers and a list of those dividers: int* dividers
This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
int amount;
int* dividers;
} Divide;
int main(){
Divide ** tt;
read_dividers(tt,5);
}
/* the functions "amount_of_dividers(int g)" and "dividers_of(int g, int amount)"
used in void read_divider are working properly, they are not needed for this question */
void read_divider(Divide *g){
scanf("%d",&(g->value));
g->amount = amount_of_dividers(g->value);
g->dividers = dividers_of(g->value,g->amount);
}
/* assuming that read_divider works, what causes read_dividerS to crash? */
void read_dividers(Divide ** t, int amount){
int i = 0;
t = malloc(amount*sizeof(Divide*));
for(i = 0;i<amount;i++){
read_divider(t[i]);
}
}
Read_dividers uses an array of pointers **t where i'm trying to fill each element of this array with a pointer to a Divide g variable.
EDIT: input in this case in main() : "read_dividers(tt,5)" means the user gives 5 int's, which get converted to 5 Divide structs.
What happens instead is the program crashes after I give in the second int
If any more information is missing, don't hesitate to ask!
You are passing an uninitialized t[i] to read_divider. t is supposed to be pointer to pointer to Divide, not pointer to Divide, you may have just got lucky on your first pass, but I suspect it failed on the very first call.

Passing a multidimensional array of variable size

I'm trying to understand what "best practice" (or really any practice) is for passing a multidimensional array to a function in c is. Certainly this depends on the application, so lets consider writing a function to print a 2D array of variable size. In particular, I'm interested in how one would write the function printArry(__, int a, int b) in the following code. I have omitted the first parameter as I'm not exactly sure what that should be.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}
The easiest way is (for C99 and later)
void printArry(int a, int b, int arr[a][b]){
/* what goes here? */
}
But, there are other ways around
void printArry(int a, int b, int arr[][b]){
/* what goes here? */
}
or
void printArry(int a, int b, int (*arr)[b]){
/* what goes here? */
}
Compiler will adjust the first two to the third syntax. So, semantically all three are identical.
And a little bit confusing which will work only as function prototype:
void printArry(int a, int b, int arr[*][*]);
This is not really an answer, but extended comment to the OP's comment question, "well you can pass the array without knowing the number of rows with this, but then how will you know when to stop printing rows?"
Answer: generally, you can't, without passing the array size too. Look at this 1-D example, which breaks the array size.
#include <stdio.h>
int procarr(int array[16], int index)
{
return array[index];
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100));
return 0;
}
Program output (although all elements initialised to 0):
768
That was undefined behaviour and there was no compiler warning. C does not provide any array overrun protection, except for array definition initialisers (although such initialisers can define the array length). You have to pass the array size too, as in
#include <stdio.h>
int procarr(int array[16], size_t index, size_t size)
{
if (index < size)
return array[index];
return -1; // or other action / flag
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100, sizeof arr / sizeof arr[0]));
return 0;
}
Program output:
-1

Pass a 2D char array to a function in C

I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.
I identify the array and the function in the main function as, and after initializing it, attempt to call it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int const ROWS = 8;
int const COLS = 8;
int main(int argc, char** argv) {
char board[ROWS][COLS];
bool canReach(char board[][], int i, int j);
//initialize array
//values of i and j given in a for loop
canReach(board, i, j);
return (EXIT_SUCCESS);
}
While writing the function outside the main function, I defined it exactly the same as I did in the main function.
bool canReach(char board[][], int i, int j){
//Functions purpose
}
When I attempt to build the program, I'm given this error twice and the program does not build:
error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
^
Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!
You can just pass arrays as function arguments with definition of their size.
bool canReach(char board[ROWS][COLS], int i, int j);
When the size is unknown, pointers are the way.
bool canReach(char* board, int i, int j);
You should know, that arrays != pointers but pointers can storage the address of an array.
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool canReach( int n, int m, char board[][m] )
{
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
{
board[i][j] = 0;
}
}
return printf( "Hello SaarthakSaxena" );
}
int main( void )
{
const int ROWS = 8;
const int COLS = 8;
char board[ROWS][COLS];
canReach( ROWS, COLS, board );
return EXIT_SUCCESS;
}
Its output is
Hello SaarthakSaxena
Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.
You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.
It also is not a good idea to use const variables for array dimensions in C. Instead
#define ROWS 8
#define COLS 8
Assuming i and j are the indexes of an element in the array, you can use the signature:
bool canReach(size_t rows, size_t cols, char board[rows][cols],
size_t i, size_t j);
This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:
bool canReach(char board[ROWS][COLS], size_t i, size_t j);
But only if using the macros above. It does not work with the const variables.
Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.
Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.
Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.

c standard library sort function from programming pearls

#include <algorithm>
#include <stdio.h>
#include <iostream>
int intcomp(int *x,int *y) { return *x-*y;};
int a[10000];
int main(void){
int i; int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
qsort(a,n,sizeof(int),intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
it is just copy of code i have two question it show me that intcomp is incompatible in this code
and also what does intcomp function?
and also what is in windows 7 EOF? how tell program that it reached EOF?
the qsort() function requires a pointer with a particular signature.
Your function has the wrong signature so it is complaining.
Your function has the signature:
int intcomp(int *x,int *y)
While qsort requires the signature:
int intcomp(void const* xp,void const* yp)
Please note the difference in the parameter types.
A corrected version of the function is:
int intcomp(void const* xp,void const* yp)
{
// Modified for C as the tag on the question changed:
// int x = *static_cast<int const*>(xp);
// int y = *static_cast<int const*>(yp);
int x = *((int const*)(xp));
int y = *((int const*)(yp));
return x-y;
}
The function qsort() is passed a function pointer as the third parameter.
This function pointer (in your case intcomp()) is used to compare values in the array passed. Each call provides pointers into the array. The result of the function should be:
Less than 0: if x is smaller than y
0: If x is equal to y
Greater than 0: If x is larger than y
First of all: the question is labeled C++ and you #include <algorithm> and <iostream>, but your code is 100% C.
Martin York already gave the answer how to correct the signature of the function you pass to qsort().
However, the "true"(TM) C++ solution would be to use std::sort<> instead of qsort!
#include <algorithm>
#include <stdio.h>
bool intcomp(int a, int b) { return a<b; }
int a[10000];
int main(void){
int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
std::sort(&a[0], &a[n], intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
Note that incomp() takes ints and not int pointers, and returns a bool. Just like operator<() would.
Also note that in this case, you could forget the intcomp and just use std::sort(&a[0], &a[n]), which will use std::less<>, which will use operator<(int, int).
intcomp is an "Int Compare" function. It is passed a pointer to 2 ints and returns 0 if they are the same, a positive value is x > y and a negative value is x < y.
qsort is passed a pointer to this function and calls it each time it wants to know how to sort a pair of values.
The docs for qsort should give you some more details.
eg http://www.cppreference.com/wiki/c/other/qsort
qsort is in stdlib.h, so include that file at the beginning. Note that algorithm and iostream aren't needed.
#include <stdlib.h>
As Martin York mentioned, qsort needs a function which it will use to compare the values:
void qsort( void *buf, size_t num, size_t size, int (*compare)(const void*, const void *) );
Here is a good example on how to use qsort: http://www.cppreference.com/wiki/c/other/qsort
Edit: Ri was faster....

Resources