tags:

views:

161

answers:

6

Hi,

I want to provide the type of an element as parameter to an initialization of an array of pointers to element of an unknown types

something like

void* init(type t)
  void* array = malloc(sizeof_type(t)*10));
  return array;
}

and later call for example

   init(typeof(int))

But I was not able to figure what is the return type of typeof.

I guess the sizeof_type think can be achieved using

   malloc((type) 0);

Thanks in advance

PS: this if for a vector implementatin if someone can point me to some flexiblecode i would be very thankful as well

A: 

I know your question wasn't tagged as such, but if you happen to be able to use C++, you may want to look into using template classes. Libraries like STL use templates to provide (type) universal containers and algorithms.

http://www.cplusplus.com/doc/tutorial/templates/

http://en.wikipedia.org/wiki/Template_%28programming%29

sigint
+2  A: 

I don't usually use gnu (I think it is only in gnu C), but I don't think it's an expression in the normal sense that you can assign its value to a variable and later use it. I think it can only be used in very specific contexts as a type.

From the docs:

The syntax of using of this keyword looks like sizeof, but the construct acts semantically like a type name defined with typedef.

A typeof-construct can be used anywhere a typedef name could be used. For example, you can use it in a declaration, in a cast, or inside of sizeof or typeof.

Uri
good to learn I can do `typeof(typeof(typof(typeof(c))))` and that it does the same as `typeof(c)` ;-)
kriss
Thanks so it is probably not possible. That basically means I have to provide a protoype element instead of the type
Ingo
+1  A: 

What you want is not possible.

typeof() does not really return a type, since it is a keyword which is evaluated at compile-time. It is replaced by the name for the type of its parameter.

Maybe you can You can not use the stringification operator of the preprocessor to make it a string, like this ##typeof(a), but then it would still be impossible to malloc/cast something when you have the type in a string.

Sjoerd
1. Stringification won't work, because typeof() cannot be evaluated at preprocessing stage. You will get just the string "typeof(a)" for your troubles.
atzz
2. "##" is actually token glueing, not stringification.
atzz
@Sjoerd. +1. and remove the last paragraph, makes no sense. from what you say typeof() is evaluated at compile time, then it is too late for preprocessor tricks.
Dummy00001
+1  A: 

This:

#define INIT(t) (malloc(sizeof(t) * 10))

may be used like this:

int* a = INIT(int);

or possibly like this:

void* b = INIT(typeof(c));

or even this:

void* b = INIT(c);

since sizeof(c) == sizeof(typeof(c)).

Alexandre C.
or even `void * b = INIT(c)` as `sizeof` accept a variable (works like if there was an implicit `typeof`)
kriss
@kriss: well spotted :)
Alexandre C.
A: 

Why can't you just use sizeof? something like:

int c;
void *p = calloc( 10,sizeof(c) );
Nyan
A: 

You can use a macro for this purpose:

#define INIT(t) ((t*) init_1(sizeof(t)))

void *init_1(size_t sz) {
  void *array = malloc(sz * 10);
  return array;
}

Then you use like:

int *array = INIT(int);
Juliano
There is no reason to cast the result. Simply use the `void *` for what it was intended for. (See casting the return value of malloc considered harmful.)
R..
@R.. You are wrong in this case. Take a better look, I'm **not** casting the return value of malloc(), so your concerns do not apply here. I'm casting the return value of init_1() so that the expression has the appropriate type. This is important, so that the compiler flags errors like assigning `INIT(int)` to a `char*`, for example. The point of not using a cast in the malloc() return is to prevent the compiler from using an implicit malloc() declaration which returns int and is casted to a pointer type, which causes UB.
Juliano
Note that, since I'm actually not casting the return of malloc(), if the user forgets to include <stdlib.h>, the compiler will issue a warning for converting an int to pointer in the line with malloc(). The type casting in the #define line is harmless, since the definition of init_1() is there, the compiler knows that the function returns a pointer, and the cast does a safe pointer to pointer conversion and causes the expression to have the correct type.
Juliano