The demo code is as follows:
#include <stdio.h>
#define DEMO(array) demo(array, sizeof(array) / sizeof(array[0]))
typedef struct Demo {
const char *msg;
} Demo;
void demo(Demo list[], size_t list_size) {
for (int i = 0; i < list_size; i++) {
printf("%s\n", list[i].msg);
}
}
int main() {
Demo d[] = {
{"Hello World"},
{"Hello World"}
};
DEMO(d);
}
I want to merge the code in the main function, the way I imagine the merge is like this:
DEMO((Demo []){
{"Hello World"},
{"Hello World"}
});
I remember seeing this kind of syntactic sugar in an open source project once, but I can't remember which project it was.
You can indeed invoke the macro with a compound literal argument, but you should be more careful in the macro definition to parenthesize all instances of its argument in the expansion, except as function arguments: sizeof(array[0]) causes a syntax error for the argument (Demo[]){{"Hello World"}, {"Hello World"}}
#include <stdio.h>
#define DEMO(array) demo(array, sizeof(array) / sizeof((array)[0]))
typedef struct Demo {
const char *msg;
} Demo;
void demo(Demo list[], size_t list_size) {
for (int i = 0; i < list_size; i++) {
printf("%s\n", list[i].msg);
}
}
int main() {
DEMO((Demo[]){{"Hello World"}, {"Hello World"}});
}
With the posted definition, you can still invoke the macro with the compound literal, but it must be parenthesized to ensure proper evaluation:
DEMO( ( (Demo[]){ {"Hello World"}, {"Hello World"}} ) );
DEMO(((Demo[]){{"Hello World"},{"Hello World"}}));
Related
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
typedef struct {
char name[128], code[128];
} info;
info db[3];
info* data=db;
void find (const char *code, int size, ...) {
bool mismatch = true;
va_list arg;
va_start(arg,size);
while (size-- > 0) {
data = va_arg(arg,info*);
printf("%s", data->code);
if (!strcmp(data->code,code))
{
printf("%s [id:%s]\n",data->name,data->code), mismatch = false;
}
}
if (mismatch) printf("No data available!");
return;
}
int main (int argc, char *argv[], char *envp[]) {
const char *spec[] = {
"Physics of Elementary Particles",
"Physics of Hign Energy",
"Low-level Programming"
};
const char *code[] = {
"2396","0812", "0773"
};`enter code here`
for (int count = 0; count < 3; ++count) {
strncpy(db[count].name,spec[count],128);
strncpy(db[count].code,code[count],128);
}
find("0812",3,db[0],db[1],db[2]);
return 0;
}
After running it says "read access violation", although I hope everything is correct, it happens after function "va_arg(arg, info*)". Is it some troubles with stack or decrypting?
The problem is in the function call:
find("0812",3,db[0],db[1],db[2]);
The variadic argument that you're passing in are of type info. However, when you retrieve them with va_arg you're looking for a info *. These don't match up.
You want to pass in the address of each array member.
find("0812",3,&db[0],&db[1],&db[2]);
Also, you need to call va_end at the bottom of find before you return.
Can you please help me with merging of two texts into one using just only stdio.h and stdlib.h? The result should be HelloWorld.
So far, I have the following, but there is a mistake somewhere.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
char *spojeni(char *t1, char *t2)
{
char pole_spolecne[10];
for (*t1 = 0; *t1 < 5; t1++)
{
pole_spolecne[*t1] = *t1;
}
for (*t2 = 0; *t2 < 10; t2++)
{
pole_spolecne[*t2 + 5] = *t2;
}
return pole_spolecne;
}
int main()
{
char pole1[] = { "Hello" };
char pole2[] = { "World" };
printf("%s\n", spojeni(pole1, pole2));
system("pause");
return 0;
}
My new solution, but it returns an error at the end:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
char *spojeni(char *t1, char *t2)
{
char pole_cele[20];
char *p_pole_cele;
p_pole_cele = t1;
strcat(p_pole_cele, t2);
return p_pole_cele;
}
int main()
{
char pole1[] = { "Hello" };
char pole2[] = { "World" };
char *p_pole1;
char *p_pole2;
p_pole1 = pole1;
p_pole2 = pole2;
printf("%s\n)", spojeni(p_pole1, p_pole2));
system("pause");
return 0;
}
Finally, this change of function helped:
char *spojeni(char *t1, char *t2)
{
char pole_cele[20];
char *p_pole_cele;
p_pole_cele = (char *)malloc(10);
strcpy(p_pole_cele, t1);
p_pole_cele = (char *)realloc(p_pole_cele, 20);
strcat(p_pole_cele, t2);
return p_pole_cele;
}
I am not quite sure how to answer this, as this is clearly a teaching exercise, and, to be blunt, the code given shows a lack of understanding of pointers. And pointers is a topic better taught in person than via a web-site comment.
A few hints, though:
Think very clearly about pointers, what they are pointing to, and what makes them different from array indices.
Draw diagrams to visualize what you're doing.
Your exercise can be solved using calloc(), strlen() and strcpy().
Say I have a function which I want to call based on the size of a type.
Is there some way this can be done using a macro?
static int array_find_index_4_impl(void *array, const unsigned int arr_len, const void *var)
{
const int32_t *arr_step = arr;
unsigned int i;
for (i = 0; i < arr_len; i++, arr_step++) {
if (*arr_step == *(int32_t *)var) {
return (int)i;
}
}
return -1;
}
static int array_find_index_2_impl(void *array, const unsigned int arr_len, const void *var)
{
const int16_t *arr_step = arr;
unsigned int i;
for (i = 0; i < arr_len; i++, arr_step++) {
if (*arr_step == *(int16_t *)var) {
return (int)i;
}
}
return -1;
}
/* etc... for other sizes too */
#define array_find_index(array, array_len, var) \
array_find_index_##SOME_MAGIC_SIZEOF(*array)##_impl(array, array_len, var)
Possible solutions...
I know C11's _Generic can be used to check for specific types, but I was interested in ignoring the exact types and finding the right function based on size only.
Another option could be to store a lookup table of functions, eg:
#define array_find_index(array, var) \
array_find_index_fn_table[sizeof(*array)](array, var)
Which can work but would prefer to construct the identifier directly if possible.
Of course its possible to pass the sizeof to a function and use memcmp, but I'm interested to know if about creating identifiers from a structs size
Another possible solution could be to generate some X-macro header file with the size of the relevant types, i.e. to generate a file like
#define MY_SIZEOF_int 4
etc etc.... using some simple C generating file containing
#define WANT_SIZE(Typ) { \
printf("#define MY_SIZEOF_%s %d\n", \
#Typ, (int) sizeof(Typ)); };
and have somewhere
WANT_SIZE(int)
WANT_SIZE(my_struct_t)
and running the specialized generator in the build process...
assuming some typedef struct my_struct_st my_struct_t before (because this works only for simply named types).
Of course, this requires complexifying the building procedure (e.g. add a couple of rules and targets in your Makefile...)
Yet another solution could be to use (with GCC...) its __builtin_type_compatible_p or even customize it (by adding your specific pragmas or builtins) using MELT.
I have a function which I want to call based on the size of a type.
Is there some way this can be done using a macro?
Using only macros, no it can't be done. Macros are expended by the preprocessor, there is no awareness of an identifier's type at this stage, let alone its size.
In other words the preprocessor just doesn't have the information needed to do what you want.
However, a solution to the original problem of having a function called based on the size of a type could of course involve some preprocessing, like the one you proposed.
#include <stdio.h>
#include <string.h>
static int array_find_index(const void *array, const void *value, size_t numOfMember, size_t element_size){//option add compare function
size_t i;
const char *p = (const char *)array;
for(i = 0; i < numOfMember; ++i, p += element_size){
if(memcmp(p, value, element_size)==0)
return (int)i;
}
return -1;
}
#define ARRAY_FIND_INDEX(array, var) \
array_find_index(array, var, sizeof(array)/sizeof(*array), sizeof(*array))
int main (void){
int ia[] = {1,2,3,4,5};
int ikey = 3;
int index = ARRAY_FIND_INDEX(ia, &ikey);
printf("%d\n", index);
char ca[] = {'1','2','3','4','5'};
char ckey = '5';
index = ARRAY_FIND_INDEX(ca, &ckey);
printf("%d\n", index);
ckey = '0';
index = ARRAY_FIND_INDEX(ca, &ckey);
printf("%d\n", index);
return 0;
}
I am trying to sort a struct run array called results by a char, but when I print the array, nothing is sorted. Have a look at this:
struct run {
char name[20], weekday[4], month[10];
(And some more...)
};
typedef struct run run;
int name_compare(const void *a, const void *b)
{
run *run1 = *(run **)a;
run *run2 = *(run **)b;
return strcmp(run1->name, run2->name);
}
int count_number_of_different_persons(run results[])
{
int i = 0;
qsort(results, sizeof(results) / sizeof(run), sizeof(run), name_compare);
for(i = 0; i <= 999; i++)
{
printf("%s\n", results[i].name);
}
// not done with this function yet, just return 0
return 0;
}
The output from the above is just a list of names in the order they were originally placed
int count_number_of_different_persons(run results[])
This doesn't really let you use sizeof on the array, because array is decayed to pointer.
This
run *run1 = *(run **)a;
also looks weird, shouldn't it be
run *run1 = (run*)a;
?
One problem is in name_compare. Try this instead:
int name_compare(const void *a, const void *b)
{
run *run1 = (run *)a;
run *run2 = (run *)b;
return strcmp(run1->name, run2->name);
}
Check the following code:
As #michel mentioned, sizeof(array) provides size of the pointer, not the size of the array itself, as while passing array it is treated as a pointer. Hence either send the number of elements to the function count_number_of_different_persons or define a MACRO of number of elements. Hope this helps. :).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NOE 3
struct run
{
char name[20];
};
typedef struct run run;
int name_compare (const void *a, const void *b )
{
return strcmp (((run *)a)->name, ((run *)b)->name);
}
int count_number_of_different_persons(run results[], int noOfElements)
{
int i=0;
qsort(results, noOfElements, sizeof (run), name_compare);
for (i=0; i<noOfElements; i++)
printf ("%s\n",results[i].name);
}
int main ( int argc, char * argv[])
{
run a, b, c;
run arg[NOE];
strcpy (a.name, "love");
strcpy (b.name, "you");
strcpy (c.name, "i");
arg[0] = a;
arg[1] = b;
arg[2] = c;
count_number_of_different_persons(arg, sizeof(arg)/sizeof(run));
};
How would I create an array of ten function pointers? What I have is a for loop, and I want to set a function pointer to a different function on each iteration. so:
//pseudocode
for i (0..10)
function = array_of_functions[i];
//...
// Define alias for function pointer type for convenience
typedef void (*action)(int);
// Example function
void print(int) { ... }
action fs[10] = { print, ... };
for (int i = 0; i < 10; ++i)
{
action f = fs[i];
// Call it somehow
f(i * i);
}
This code:
return_t (*array_of_functions[10])(arg1_t, arg2_t);
Declares "array_of_functions" as a 10-element array of function pointers where each pointed-to function takes two arguments of type arg1_t and arg2_t and returns type return_t. Replace types and adjust the number of arguments as appropriate.
Any time you have to deal with ugly function pointer syntax it's better to use a typedef.
#include <iostream>
void a(int i)
{
std::cout<<"a: "<<i<<std::endl;
}
void b(int i)
{
std::cout<<"b: "<<i<<std::endl;
}
typedef void (*fn)(int);
int main(int argc, char**argv)
{
fn foo[2];
foo[0] = a;
foo[1] = b;
for(size_t i = 0; i < sizeof(foo) / sizeof(foo[0]); ++i)
{
foo[i](i);
}
return 0;
}
The simplest way to do it is to create a typedef for your function, and then declare an array with that type. To create a typedef for the function: typedef returntype (*typedefname)(argtype1,argtype2,...,argtypeN); EX:
#include <stdio.h>
#include <stdlib.h>
typedef void (*functype)();
void func1()
{
//...
}
void func2()
{
//..
}
//...
void func10()
{
//...
}
int main(int argc, char* argv[])
{
functype array[] =
{
&func1,
&func2,
&func3,
&func4,
&func5,
&func6,
&func7,
&func8,
&func9,
&func10
};
// Use the array...
return 0;
}
T (*array_of_functions[10])();
Where T is the return type of each function (all functions return the same type, naturally). Things get tricky if you want to store pointers to functions with different numbers/types of parameters:
int foo(void) {...}
int bar(int x) {...}
int bletch(double y, double z) {...}
...
int (*array_of_functions[10])() = {foo, bar, bletch, ...};
If so, you'll have to keep track of what number and types of parameters each function requires somehow so you can call it correctly.
I'm actually kind of down on typedefs for function pointer types; they tend to obscure as much as they simplify.