I've found that there are conditions that the second argument of va_start(ap, last) must satisfy, which are:
last must not be a register variable
last must not be a function
last must not be an array
(Sources: stdarg(3), cppreference)
Though the manual page explains the reason these constraints exist, but I don't seem to understand the implication.
Does that mean the following code is wrong? In this code, iterate_string takes a function of type processor_t and variable arguments follow this parameter.
/*
* A program that skips or reads some characters
* from the external variable `src` and stores
* them into `buf`.
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
/* External variables */
const char *src = "UwU Chino chan is so cute!!";
const int src_len = 22;
int src_idx = 0; /* position in src */
char ch, buf[128];
int buf_idx; /* position in buf */
/* Typedefs */
typedef int processor_t(va_list *ap_ptr);
typedef int checker_t(va_list *ap_ptr);
/*
* Iterate 'src' by invoking `process`.
* If `process` returns 0, stops the iteration.
*/
void iterate_string(processor_t process, ...) {
va_list ap_is; /* is = iterate string */
while (src_idx < src_len) {
va_start(ap_is, process);
if (!process(&ap_is))
break;
}
va_end(ap_is);
return;
}
/*
* Store a character into `buf`.
* If `check` returns 0, stops the storing.
*/
int process_storing(va_list *ap_ptr) {
checker_t *check;
check = va_arg(*ap_ptr, checker_t *);
ch = src[src_idx++];
if ((*check)(ap_ptr)) {
buf[buf_idx++] = ch;
return 1;
}
else {
buf[buf_idx] = '\0';
return 0;
}
}
/*
* Just skip a character.
* If `check` returns 0, stops the skipping.
*/
int process_leaving(va_list *ap_ptr) {
checker_t *check;
check = va_arg(*ap_ptr, checker_t *);
ch = src[src_idx];
if ((*check)(ap_ptr)) {
src_idx++;
return 1;
}
else
return 0;
}
/*
* Sees whether `cnt` is less than a number.
* If not, returns.
*/
int check_count_less_than(va_list *ap_ptr) {
static int cnt = 0;
int n;
n = va_arg(*ap_ptr, int);
if (cnt < n) {
cnt++;
return 1;
}
else {
cnt = 0;
return 0;
}
}
/*
* Read `src` and store `n` characters into `buf`.
*/
void store_nchar(int n) {
buf_idx = 0;
iterate_string(process_storing, check_count_less_than, n);
}
/*
* Read `src` and skip `n` characters.
*/
void leave_nchar(int n) {
iterate_string(process_leaving, check_count_less_than, n);
}
int main(void) {
leave_nchar(4); /* Skip "UwU " */
store_nchar(5); /* Save "Chino" */
// Daily greetings
printf("Me: Hi, %s chan! How are you today?\n", buf);
printf("%s: I'm sorry... Do I know you?\n", buf);
return 0;
}
Although this code seems working (at least in my machine) but I'm not sure whether my code is good or bad. Should I have iterate_string have a pointer to processor_t? Please explain as easy as possible.