Macro with Parameters - c

In the code which follows, I keep getting an error. How to modify the third line? Why's that keep happening? What's wrong?
#include <stdio.h>
#include "stdlib.h"
#define ARRAY_IDX(type, array, i) ((type *)(array+i)) // you can only modify this line!
int main(int argc, const char * argv[]) {
void *ptr = malloc(10*sizeof(int));
#ifdef ARRAY_IDX
for (int i = 0; i < 10; i++) {
ARRAY_IDX(int, ptr, i) = i * 2;
}
for (int i = 0; i < 10; i++) {
printf("%d ", ARRAY_IDX(int, ptr, i));
}
free(ptr);
#else
printf("Implement ARRAY_IDX first");
#endif
}

Looking at
ARRAY_IDX(int, ptr, i) = i * 2;
and
printf("%d ", ARRAY_IDX(int, ptr, i));
shows that the expression
ARRAY_IDX(int, whatever, whatever)
should expand into an expression of type int (and an lvalue, so that we can assign to it).
Starting off with a void * you first need to change (cast) it to a pointer that allows indexing, and since you want to index the elements of that array (not its individual bytes, which would be a violation of aliasing) you need to make it an int * first:
(int *)(ptr)
Now you have a pointer to an integer (array, hopefully). Increment it:
(int *)(ptr) + (idx)
Finally, you need an lvalue int expression. Dereference the pointer to get that:
(*((int *)(ptr) + (idx)))
Converting that to a preprocessor macro is something that should be doable, so I leave it up to you.
Note that whoever is giving you that code is - IMHO - not a teacher you should trust. This won't teach you much about correct C. It might teach you something about the preprocessor. But don't write such code. Just don't. Use correct types if possible. Check for failure of malloc.

There is nothing wrong with adding an int to a void pointer. For many years, compiler designers assumed that this was standard behavior, and it was implemented as such. It's every bit as standard as anonymous structs and unions, which compilers have had for almost 20 years and were only recently added in C11. Practically all compilers will compile this just fine without any warnings or errors, and without having to use any special compiler flags.
Your problem is, as I have pointed out, that you are assigning a value to a pointer. You need to dereference it after the cast.
#define ARRAY_IDX(type, array, i) ((type *)array)[i]

Related

Getting operator sizeof to differentiate among simple address, pointer and array (possibly with a macro?)

I would like to pass as the second argument to function mem the "correct" size of its first argument, which is an address to void.
I thought of using a macro, MEM, which uses the operator sizeof. This macro is supposed to "infer" at pre-processing time the "correct" size by looking at the text, i.e. how the first argument is written in code.
Except my macro it does not work well when the argument is an array that is passed with the name of the array (arr). (Note that the macro works well if I pass &arr, as suggested in the comments)
#include <stdio.h>
#define MEM(addr) mem(addr,sizeof *addr) // <-- does not work for arrays
void mem(const void* , int );
int main()
{
int t=3;;
int arr[10];
int* p=&t;
MEM(&t); // --> mem(&t,sizeof *&t) <- OK!
MEM(p); // --> mem(p,sizeof *p <- OK!
MEM(arr); // --> mem(arr,sizeof *arr) <- NO! I WANT THE SIZE OF THE ALL ARRAY!
// SO I WANT --> mem(arr,sizeof arr)
return 0;
}
void mem(const void* pp, int bytestoread) // prints bytestoread bytes starting from address pp
{
int i;
unsigned char* p=(unsigned char*)pp;
for(i=0;i<bytestoread;i++)
{
if(i%8==0)
{
if(i!=0) printf("\n");
printf("%p: ",p);
}
printf("%02x ",*p);
p++;
}
printf("\n\n");
}
If there's a different solution or approach to my problem other then a macro, even better. But arrays decay when passed as parameters to a function, so I don't see how I can use a function to accomplish what I want.
I would be happy even if there was some hack with the C preprocessor, like using the stringizing preprocessor operator # on the name of the address written in code and selectively compile MEM accordingly, but I couldn't do that. (maybe using also the #if #else #endif preprocessor directives ...? )
FOLLOW-UP:
The following would be a tentative solution that exploits the fact that for an array arr (as opposed to a regular pointer) &arr==arr...
#define SIZE(add) ( #add[0]=='&' ?
sizeof *add :
((void*)add==(void*)&add ? sizeof add : sizeof *add) )
#define MEM(address) mem( address, SIZE(address) )
...but of course this, as is, doesn't compile when address is written as &t in the code (where t is an int for example), because &&t is not syntactically correct, even if the check #add[0]=='&' makes sure it would never be executed.
1) Is there a way to make it work?
2) Or should I write a parser that outputs the code I want to be compiled based on the text I pass to the parser?
3) Why is the C pre-processor so strict regarding what I can use as a condition in #if directives? (I cannot even use string literals nor # operator! Only const expressions like 2>1 or other defined macro are allowed)
It seems that there is no obvious solution with MEM macro, although there might be a solution with preprocessor condition expressions where according to the type of the operand we decide how to calculate the size.
The common practice in C is creating functions with an extra argument that takes the size of the data container. So you would write something like this, without macro usage at all:
int t = 3;
int arr[10] = {0};
int *p = &t;
mem(&t, sizeof(t));
mem(p, sizeof(*p));
mem(arr, sizeof(arr) / sizeof(arr[0])); // <- 40/4 = 10
This is quite verbose but in this case, you could rely on this and be sure that you're getting the expected behavior.

Segfault when trying to index pointer to pointers in function

I'm trying to do something with an array (malloc-ed), namely arr of a custom struct. The array is passed by reference to a function. I get a segfault whenever I tried to index anything other than arr[0] in the function at runtime (e.g (*arr[1])->i = 3;). Why is this happening?
The full source code is:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef struct{
int i;
float f;
}foo;
void doSomething(foo ***arr);
int main()
{
foo **arr = (foo**) malloc (SIZE * sizeof(foo*));
int i;
for(i = 0; i < SIZE; i++)
arr[i] = (foo*)malloc(sizeof(foo));
arr[1]->i = 1;
printf("Before %d\n",arr[1]->i );
doSomething(&arr);
printf("After %d\n",arr[1]->i );
return 0;
}
void doSomething(foo ***arr)
{
(*arr[1])->i = 3;
}
Your problem is the line
(*arr[1])->i = 3;
Because the subscripting operator's evaluation precedes the dereferencing's evaluation it is equivalent to the following:
(*(arr[1]))->i = 3;
This is obviously wrong. You need
(*arr)[1]->i = 3;
therefore.
Notes:
do not cast the result of malloc
add #include <stdlib.h> to resolve the warning
adding an extra level of indirection (foo*** pointing to foo**) is unnecessary; just copy by value
(in addition to the upper note) a good old 1D array should actually be sufficient in your case
call free after malloc
The warning you get is because you forgot to #include <stdlib.h>, so malloc is not declared, so the compiler assumes it should return int. This can lead to all kinds of fun problems. (And you should remove those casts.)
The other problem is in this line: (*arr[1])->i = 3;
Postfix operators (like []) bind tighter than prefix operators (like *), so *arr[1] parses as *(arr[1]).
You can write (*arr)[1]->i instead to fix this, but as it turns out, your function never actually modifies *arr, so there's no reason to pass arr (the other arr, the one in main)'s address to it. Just do this:
void doSomething(foo **arr)
{
arr[1]->i = 3;
}
and call it as doSomething(arr).

Convert a non-pointer variable to a pointer to an array

Ok, I understand that my title might be a bit confusing, but I'll explain. I'm working on a homework assignment in C. I'm given a .c file and need to come up with implementations for some functions.
In short, I have this as a .c file
typedef int set_t;
...
void init(set_t *a, int N); // Initialized an array to a of size N
...
int main() {
set_t a;
init(&a, 10);
}
In a couple of implementations I've come up with, I was able to create an array using a, but I keep getting segmentation faults when the program runs :-/. Is there away to initialize a as an array without changing anything in the original .c file except for the implementation of init(set_t *a, int N)?
EDIT
Here's my current implementation of init --> it leads to a segmentation fault
void init(set_t *a, int N) {
//set_t thing[10];
*a = malloc(sizeof(set_t)*N);
for (int i = 0; i < N; i++) {
*(a + i) = i;
}
printf("value of a[2] = %d\n", a[2]);
}
As things currently stand, the requirements imposed on you are wholly unreasonable. If you are building for 32-bit only, so sizeof(int) == sizeof(int *), then you can use brutal casting to get around the constraints. The code will not work on a 64-bit machine, though (unless sizeof(int) == sizeof(int *), which isn't the case on any machine I can immediately think of.
So, the brute force and casting technique is:
void init(set_t *a, int N)
{
assert(sizeof(set_t) == sizeof(set_t *)); // Ick, but necessary!
set_t *base = malloc(sizeof(set_t)*N);
if (base == 0)
*a = 0;
else
{
*a = (int)base; // Brutal; non-portable; stupid; necessary by the rules given!
for (int i = 0; i < N; i++) {
base[i] = i;
printf("value of a[2] = %d\n", base[2]);
printf("value of a[2] = %d\n", ((int *)*a)[2]); // Brutal and stupid too
}
}
Further, in the code in main(), you'll have to use ((int *)a) to make the type usable for dereferencing, etc. Without knowing about what is actually in that other code, it is impossible to be confident that anything will work. It might, but it probably won't.
At this stage, this looks like someone criminally misleading innocent novice programmers. This is not the way it should be coded at all. However, if that's what the doctor (professor) orders, then that's what you've got to do. But it is a mockery of good coding practices AFAICS and AFAIAC.
Professor realized that he had made an error in the assignment and fixed it. Changed set_t a to set_a *a.
Thanks for all your help (hope I didn't cause too many headaches!

How to make generic function using void * in c?

I have an incr function to increment the value by 1
I want to make it generic,because I don't want to make different functions for the same functionality.
Suppose I want to increment int,float,char by 1
void incr(void *vp)
{
(*vp)++;
}
But the problem I know is Dereferencing a void pointer is undefined behaviour. Sometimes It may give error :Invalid use of void expression.
My main funciton is :
int main()
{
int i=5;
float f=5.6f;
char c='a';
incr(&i);
incr(&f);
incr(&c);
return 0;
}
The problem is how to solve this ? Is there a way to solve it in Conly
or
will I have to define incr() for each datatypes ? if yes, then what's the use of void *
Same problem with the swap() and sort() .I want to swap and sort all kinds of data types with same function.
You can implement the first as a macro:
#define incr(x) (++(x))
Of course, this can have unpleasant side effects if you're not careful. It's about the only method C provides for applying the same operation to any of a variety of types though. In particular, since the macro is implemented using text substitution, by the time the compiler sees it, you just have the literal code ++whatever;, and it can apply ++ properly for the type of item you've provided. With a pointer to void, you don't know much (if anything) about the actual type, so you can't do much direct manipulation on that data).
void * is normally used when the function in question doesn't really need to know the exact type of the data involved. In some cases (e.g., qsort) it uses a callback function to avoid having to know any details of the data.
Since it does both sort and swap, let's look at qsort in a little more detail. Its signature is:
void qsort(void *base, size_t nmemb, size_t size,
int(*cmp)(void const *, void const *));
So, the first is the void * you asked about -- a pointer to the data to be sorted. The second tells qsort the number of elements in the array. The third, the size of each element in the array. The last is a pointer to a function that can compare individual items, so qsort doesn't need to know how to do that. For example, somewhere inside qsort will be some code something like:
// if (base[j] < base[i]) ...
if (cmp((char *)base+i, (char *)base+j) == -1)
Likewise, to swap two items, it'll normally have a local array for temporary storage. It'll then copy bytes from array[i] to its temp, then from array[j] to array[i] and finally from temp to array[j]:
char temp[size];
memcpy(temp, (char *)base+i, size); // temp = base[i]
memcpy((char *)base+i, (char *)base+j, size); // base[i] = base[j]
memcpy((char *)base+j, temp, size); // base[j] = temp
Using void * will not give you polymorphic behavior, which is what I think you're looking for. void * simply allows you to bypass the type-checking of heap variables. To achieve actual polymorphic behavior, you will have to pass in the type information as another variable and check for it in your incr function, then casting the pointer to the desired type OR by passing in any operations on your data as function pointers (others have mentioned qsort as an example). C does not have automatic polymorphism built in to the language, so it would be on you to simulate it. Behind the scenes, languages that build in polymorphism are doing something just like this behind the scenes.
To elaborate, void * is a pointer to a generic block of memory, which could be anything: an int, float, string, etc. The length of the block of memory isn't even stored in the pointer, let alone the type of the data. Remember that internally, all data are bits and bytes, and types are really just markers for how the logical data are physically encoded, because intrinsically, bits and bytes are typeless. In C, this information is not stored with variables, so you have to provide it to the compiler yourself, so that it knows whether to apply operations to treat the bit sequences as 2's complement integers, IEEE 754 double-precision floating point, ASCII character data, functions, etc.; these are all specific standards of formats and operations for different types of data. When you cast a void * to a pointer to a specific type, you as the programmer are asserting that the data pointed to actually is of the type you're casting it to. Otherwise, you're probably in for weird behavior.
So what is void * good for? It's good for dealing with blocks of data without regards to type. This is necessary for things like memory allocation, copying, file operations, and passing pointers-to-functions. In almost all cases though, a C programmer abstracts from this low-level representation as much as possible by structuring their data with types, which have built-in operations; or using structs, with operations on these structs defined by the programmer as functions.
You may want to check out the Wikipedia explanation for more info.
You can't do exactly what you're asking - operators like increment need to work with a specific type. So, you could do something like this:
enum type {
TYPE_CHAR,
TYPE_INT,
TYPE_FLOAT
};
void incr(enum type t, void *vp)
{
switch (t) {
case TYPE_CHAR:
(*(char *)vp)++;
break;
case TYPE_INT:
(*(int *)vp)++;
break;
case TYPE_FLOAT:
(*(float *)vp)++;
break;
}
}
Then you'd call it like:
int i=5;
float f=5.6f;
char c='a';
incr(TYPE_INT, &i);
incr(TYPE_FLOAT, &f);
incr(TYPE_CHAR, &c);
Of course, this doesn't really give you anything over just defining separate incr_int(), incr_float() and incr_char() functions - this isn't the purpose of void *.
The purpose of void * is realised when the algorithm you're writing doesn't care about the real type of the objects. A good example is the standard sorting function qsort(), which is declared as:
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
This can be used to sort arrays of any type of object - the caller just needs to supply a comparison function that can compare two objects.
Both your swap() and sort() functions fall into this category. swap() is even easier - the algorithm doesn't need to know anything other than the size of the objects to swap them:
void swap(void *a, void *b, size_t size)
{
unsigned char *ap = a;
unsigned char *bp = b;
size_t i;
for (i = 0; i < size; i++) {
unsigned char tmp = ap[i];
ap[i] = bp[i];
bp[i] = tmp;
}
}
Now given any array you can swap two items in that array:
int ai[];
double ad[];
swap(&ai[x], &ai[y], sizeof(int));
swap(&di[x], &di[y], sizeof(double));
Example for using "Generic" swap.
This code swaps two blocks of memory.
void memswap_arr(void* p1, void* p2, size_t size)
{
size_t i;
char* pc1= (char*)p1;
char* pc2= (char*)p2;
char ch;
for (i= 0; i<size; ++i) {
ch= pc1[i];
pc1[i]= pc2[i];
pc2[i]= ch;
}
}
And you call it like this:
int main() {
int i1,i2;
double d1,d2;
i1= 10; i2= 20;
d1= 1.12; d2= 2.23;
memswap_arr(&i1,&i2,sizeof(int)); //I use memswap_arr to swap two integers
printf("i1==%d i2==%d \n",i1,i2); //I use the SAME function to swap two doubles
memswap_arr(&d1,&d2,sizeof(double));
printf("d1==%f d2==%f \n",d1,d2);
return 0;
}
I think that this should give you an idea of how to use one function for different data types.
Sorry if this may come off as a non-answer to the broad question "How to make generic function using void * in c?".. but the problems you seem to have (incrementing a variable of an arbitrary type, and swapping 2 variables of unknown types) can be much easier done with macros than functions and pointers to void.
Incrementing's simple enough:
#define increment(x) ((x)++)
For swapping, I'd do something like this:
#define swap(x, y) \
({ \
typeof(x) tmp = (x); \
(x) = (y); \
(y) = tmp; \
})
...which works for ints, doubles and char pointers (strings), based on my testing.
Whilst the incrementing macro should be pretty safe, the swap macro relies on the typeof() operator, which is a GCC/clang extension, NOT part of standard C (tho if you only really ever compile with gcc or clang, this shouldn't be too much of a problem).
I know that kind of dodged the original question; but hopefully it still solves your original problems.
You can use the type-generic facilities (C11 standard). If you intend to use more advanced math functions (more advanced than the ++ operator), you can go to <tgmath.h>, which is type-generic definitions of the functions in <math.h> and <complex.h>.
You can also use the _Generic keyword to define a type-generic function as a macro. Below an example:
#include <stdio.h>
#define add1(x) _Generic((x), int: ++(x), float: ++(x), char: ++(x), default: ++(x))
int main(){
int i = 0;
float f = 0;
char c = 0;
add1(i);
add1(f);
add1(c);
printf("i = %d\tf = %g\tc = %d", i, f, c);
}
You can find more information on the language standard and more soffisticated examples in this post from Rob's programming blog.
As for the * void, swap and sort questions, better refer to Jerry Coffin's answer.
You should cast your pointer to concrete type before dereferencing it. So you should also add code to pass what is the type of pointer variable.

runtime datatype working in c, how does sizeof work?

As we know, we can use int (*p)[10] to define a pointer which points to an int[10] array, so if we have p=0 and sizeof(int)==4, p+1 will be 0+10*4 = 40, this works because the compiler knows what p is when compiling.
And then what if we do it like this:
int main()
{
int sz = 10;
int (*p)[sz];
}
in other words, nobody would know the sz until the program runs there. I supposed this should not be working, but it does work..
So my question is, how it works? I mean, is there any place that store a value's type in c at runtime? If not, how this could work? Of this is just compiler-related?
I am using gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5), and you can test it with the following code.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int COL ;
int ROW ;
scanf("%d %d", &COL, &ROW);
int (*p)[COL];
int *mem = (int*)malloc(sizeof(int)*COL*ROW);
memset(mem,0,sizeof(int)*COL*ROW);
p = (int (*)[10])mem;
printf("0x%p\n", p);
printf("COL=%d\n", p+1, (((int)(p+1))-((int)p))/sizeof(int));
mem[2*COL+0] = 1;
printf("%d\n", p[2][0]);
mem[2*COL+5] = 2;
printf("%d\n", p[2][5]);
mem[6*COL+7] = 3;
printf("%d\n", p[6][7]);
p[1][2] = 4;
printf("%d\n", mem[1*COL+2]);
free(p);
return 0;
}
I hope I am not asking a stupid question nor making stupid mistake...
Pointer arithmetic on variable length array types is well defined per 6.5.6:10, which has example code very similar to yours. Per 6.5.3.4:2, when sizeof is applied to a variable length array, the operand is evaluated at runtime to determine the size, so variable length array pointer arithmetic proceeds likewise.
Variable length arrays (6.7.6.2:4) have been part of the standard since the second edition (ISO/IEC 9899:1999 as amended); they are however an optional feature that conformant implementations do not have to support (6.10.8.3).

Resources