I have this:
long int addsquares(int n, ...)
How can I access the parameters?
I can't use va_start and va_arg...
Implementation dependent...
pre test
long int addsquares(int n, int d1, ...){
printf("%p,%p\n", &n, &d1);
return 0L;
}
result :
windows 64bit system, vc10 (sizeof int:4)
003DFD54,003DFD58
windows 64bit system, gcc 4.4.3 (sizeof int:4)
000000000022FE60,000000000022FE68
for vc10:
long int addsquares(int n, ...){
int i, *p = &n;
long sum = 0L;
for(i=1;i<=n;++i)
sum += p[i]*p[i];
return sum;
}
for gcc:
long int addsquares(int n, ...){
int i, *p = &n;
long sum = 0L;
for(i=1;i<=n;++i)
sum += p[i*2]*p[i*2];
return sum;
}
If you are saying that you have a variadic function, and you're not allowed to use the variable argument macros (va_xxx) then you'd have to rewrite the content of those macro's yourself.
Unless you can change the function prototype, but I'm guessing that's now allowed either.
Use Arrays and store each parameter in one "cell" of the array.
long int addsquares(int[] parameters)
{
for (int i = 0; i < parameters.length(); i++)
{
//Use current parameter: parameters[i]
}
}
It's c# code, but i thinkit will work for c as well.
Check out the discussion in this thread... How does the C compiler implement functions with Variable numbers of arguments?
I think you'll find it gets you going in the right direction. Pay particular attention to the discussion on the need to use one of the arguments as a means to sort out what and where the other arguments are.
Related
I have the following function that accepts a varying number of integer parameters and returns the sum.
int sum(int a, ...){
va_list nums;
va_start(nums, a);
int res=0;
for(int i=0; i<a; i++) {
res += va_arg(nums, int);
}
va_end(nums);
return res;
}
I need to pass each value of the array as a parameter to the function rather than passing the array itself. The array can be of varying length leading to a varying length of arguments to pass too.
printf("The sum is: %d", sum(size, args[0], args[1], ```need all elements of args[] array here```));
To put forth some perspective, I'm using this sum function to understand how I can go about doing this. It would be helpful to know how to achieve this in a more general setting rather than this exact function.
Please let me know if you need any more information.
Please do look at this question, which is similar, however, I require a solution in C.
The short answer is that there's no way to do exactly this in the C language. There is no ES6-like spread operator in C, nor similar functionality. I don't think there's any particular reason why they couldn't (you would just have to push more arguments onto the stack); they just never made one.
However, there are various other things you can do:
If variadic arguments were already passed into the function calling your function, you can pass along the va_list to a function declared to take a va_list. See Passing variable arguments to another function that accepts a variable argument list
As #JonathanLeffer suggests, the most natural way to write this code in C is by constructing an array of what "would be" your variadic arguments, and passing that into a function that expects an array (well, technically, a pointer, because arrays decay to pointers). For example:
int sum_array(int a, int nums[]){
int res=0;
for(int i=0; i<a; i++) {
res += nums[i];
}
return res;
}
In certain circumstances, it may be more convenient for a function like sum_array to take only the nums array/pointer, which would itself indicate the end of the array with a 0 or -1 value in the last slot. This is just another convention for indicating the end, which the caller has to set up.
You could then, if you really wanted to, write a variadic function that collects its arguments into an array and calls sum_array, if you want a variadic version as well. (Of course, you could also just implement the variadic and array versions separately, but for nontrivial functions it may be a pain to implement them twice.)
int sum_variadic(int a, ...){
va_list nums;
va_start(nums, a);
int arr[a];
for(int i=0; i<a; i++) {
arr[i] = va_arg(nums, int);
}
va_end(nums);
return sum_array(a, arr);
}
you could also use a variadic macro for the same purpose:
#define sum_macro(size, ...) sum_array(size, (int[]){__VA_ARGS__})
In summary: going from variadic to array in C is trivial, going from array to variadic is impossible.
You can also use extensions to the C language to do it anyway, as described in Passing a dynamic set of variadic arguments to a C function and In C, given a variable list of arguments, how to build a function call using them?, which #KamilCuk linked to.
You can avoid passing the number of arguments explicitly by using a variadic macro that constructs a compound literal array instead of a vararg function:
#include <stdio.h>
#define sum_int(...) (sum_int)(sizeof((int[]){__VA_ARGS__}) / sizeof(int), (int[]){__VA_ARGS__})
int (sum_int)(size_t count, const int *a) {
int sum = 0;
for (size_t i = 0; i < count; i++) {
sum += a[i];
}
return sum;
}
int main() {
printf("sum = %d\n", sum_int(1, 2, 3));
return 0;
}
This approach can be used for any purpose, as long as the types of the variable arguments are converted implicitly to the array type.
If you want to pass just the arguments to your sum function without changing its definition, you can use a variation of the macro:
#include <stdio.h>
int sum(int a, ...) {
va_list nums;
va_start(nums, a);
int res = 0;
for (int i = 0; i < a; i++) {
res += va_arg(nums, int);
}
va_end(nums);
return res;
}
#define sum(...) (sum)((int)(sizeof((int[]){__VA_ARGS__}) / sizeof(int)), __VA_ARGS__)
int main() {
printf("sum = %d\n", sum(1, 2, 3));
return 0;
}
Note however that there is no type checking with this approach and sum(1, 2.0, 3) would have undefined behavior.
The example is taken from Wikipedia:
void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val)
{
*ptrA += *val;
*ptrB += *val;
}
I call this function in the main():
int main(void)
{
size_t i = 10;
size_t j = 0;
updatePtrs(&i, &j, &i);
printf("i = %lu\n", i);
printf("j = %lu\n", j);
return 0;
}
The val pointer is not be loaded twice according to the Wikipedia's description, so the value of j should be 10, but it's 20 in fact.
Is my comprehension about this keyword not correct? Should I utilize some specific options of gcc?
Thanks in advance.
Your code causes undefined behaviour. restrict is a promise from you to the compiler that all of the pointer parameters point to different memory areas.
You break this promise by putting &i for two of the arguments.
(In fact, with restrict it is allowed to pass overlapping pointers, but only if no writes are done through any of the overlapping pointers within the function. But typically you would not bother with restrict if there is no writing happening).
FWIW, on my system with gcc 4.9.2, output is j = 20 at -O0 and j = 10 at -O1 or higher, which suggests that the compiler is indeed taking note of the restrict. Of course, since it is undefined behaviour, your results may vary.
I'm trying to use FFTPACK converted from Fortran to C that I downloaded from Netlib (http://www.netlib.org/fftpack/). Unfortunately it seems to not really documented, and very cryptic (as I imagine most FFT codes are). Apparently it should follow a similar structure to the original Fortran code, so that's what I tried.
Here's what I have so far:
void main()
{
int n = 10;
float* wsave;
forward_transform(function1, wsave, n);
}
void forward_transform(float (*f)(float), float* wsave, int n)
{
int *ifac;
int i;
float r[n];
for (i = 0; i< n; i++)//set function values
{
r[i] = f((float)(-M_PI + i*2*M_PI/(n-1)));
}
__ogg_fdrffti(n, *wsave, *ifac);//initialize
__ogg_fdrfftf(n, *r, *wsave, *ifac);//forward transform
}
This code manages to compile, but gives a segfault when I call __ogg_fdrffti. I tried entering via gbd into fft.c to see exactly where the error is, but I can't seem to do that (the code still segfaults at the same line in my forward_transform function) leading me to believe that I'm somehow making an error in how I'm passing the various arrays.
Does anyone have any experience with or examples of the C version of FFTPACK?
The variables initialized in these functions have to exist somewhere in memory. You are passing pointers instead.
Try
void main()
{
int n = 10;
float wsave;
forward_transform(function1, wsave, n);
}
void forward_transform(float (*f)(float), float wsave, int n)
{
int ifac;
int i;
float r[n];
for (i = 0; i< n; i++)//set function values
{
r[i] = f((float)(-M_PI + i*2*M_PI/(n-1)));
}
__ogg_fdrffti(n, &wsave, &ifac);//initialize
__ogg_fdrfftf(n, r, &wsave, &ifac);//forward transform
}
Notice that the pointers are created using the address operator & on actual variables.
I am having an issue with double arguments for a probability function in C.
I have a function that takes a double as an argument:
int binomrand(double p, int n)
{
int i;
int numevents = 0;
for(i = 0; i < n; i++)
{
numevents += bernoullirand(p);
}
return numevents;
}
I pass .85:
int numcoach = binomrand(.85,COACH_SEATS);
but the minute I step into this function, Xcode shows p as such:
p double 5.2511106800094658E-315
Which is off by a factor of at least 10^314. This occurs even before calling bernoullirand, so I haven't included that code here.
E:
Since it was relevant, here was the .h declaration of binomrand:
int binomrand(float p, int n);
This was clearly wrong, but I didn't think to look at it. Note that's "float" and not "double".
When I updated the function from float to double in its .c file, I neglected to do so in its .h file. Multiple answerers realized this quickly.
This can happen if you have not declared the function binomrand before first use or declared it incorrectly. Declare the function on the top of file where you actually use it or use proper header files.
int binomrand(double p, int n); /* Declaration */
I'm following LCTHW tutorial and I have a task to do.
This is the data structure:
typedef struct DArray {
int end;
int max;
size_t element_size;
size_t expand_rate;
void **contents;
} DArray;
I have declared a typedef:
typedef int (*DArray_compare) (const void *a, const void *b);
When I create a sorting function, I pass to it a DArray_compare, the problem is that I can't figure out how to do an example of this comparator.
I tried to do something like this:
int compare(const void *a, const void *b)
{
int i = (int)*a;
int k = (int)*b;
printf("%d %d\n", i, k);
return i - k;
}
But I get an error:
error: operand of type 'void' where arithmetic or pointer type is required int i = (int)*a;
The question is: without changing the struct and the typedef of the comparator, I want to create a comparator that compares int, how can I do it?
int i = *(int*)a;
// This one has more parens to make it really obvious what your intent is.
int k = *((int*)b);
The second line (k=) is easiest to explain cos of all the brackets. You can rewrite it as follows:
// Cast b from a pointer to a void into a pointer to an int.
int *X = (int*)b;
// k = "what X is pointing to" or "the contents of X"
int k = *X;
edit:
I think ralu's comment is suggesting you change all the void* to int* which is a much safer solution if you have that power.
typedef int (*DArray_compare) (const int *a, const int *b);
int compare(const int *a, const int *b)
{
int i = *a;
int k = *b;
...
A comparison function for use with bsearch() or qsort() from the standard C library for arrays of DArray structures might look like:
int compare(const void *a, const void *b)
{
const DArray *d1 = a;
const DArray *d2 = b;
if (d1->end < d2->end)
return -1;
else if (d1->end > d2->end)
return +1;
else if (d1->max < d2->max)
return -1;
else if (d2->max > d2->max)
return +1;
else
return 0;
}
Clearly, if you need to compare other fields, you can add those comparisons into the framework above quite easily. The general structure of the function is my recommended way of writing such comparators. You can add explicit casts to the assignment lines if you wish; C++ would require them, but C does not.
Note that your typedef is of minimal relevance to the comparator itself (though the comparator as a function pointer should match that typedef). It is the type that a comparator should have, but you can't use that typedef name when writing the function. You could use the typedef in the implementation of the sort function and in its declaration.
I observed in a couple of places that returning the difference of two signed int values as the result of the comparator leads to undefined behaviour.
In a comment to a now deleted answer, AR89 asked:
Instead of the subtraction an if statement would be safer?
Yes. Consider what happens if you have 16-bit int values and you compare -30,000 and +30,000; you've got signed overflow, and you might get a positive value back from your comparator, even though the first value is less than the second. Analogous situations can occur with 32-bit or 64-bit integers. They're relatively unlikely; if you know that your values are well within range, you'd be OK. But for general purpose code, you should do the piecewise comparison:
if (i < k)
return -1;
else if (i > k)
return +1;
else
return 0;
as it works regardless of the values of i and k. Also note that the if comparison works reliably for unsigned int types too, whereas subtraction really doesn't work then (the result is always zero or positive).