0

Say I have a function that accepts an int:

void foo(int a) {
...
}

What kinds of check can I include in foo's body to ensure that what is passed in is indeed an int? As it stands now, if I pass in a float for example it simply is truncated to an int. It would be great to have something like Java's instanceof keyword, but I guess that's probably too much to hope for.

Adam
  • 8,752
  • 12
  • 54
  • 96
  • 1
    Create 2 functions `foo_i(int a)` and `foo_f(float a)` and a `_Generic()` macro `foo()` to call them. The `foo_f(float a)` can do additional testing before calling `foo_i(int a)`. – chux - Reinstate Monica Jan 26 '16 at 03:33
  • 2
    Can you tell us what you want to achieve by checking the type? – B. Kostas Jan 26 '16 at 03:36
  • @M.Kostas I want to prevent unexpected behaviour from occuring. For example, say `foo()` is creating a node in a linked list and `a` is the value we want to assign the node. If somone passes in 6.5 the function wouldn't complain, but as a result there would be a node with a value of 6 in our list instead of 6.5 as the user expects. – Adam Jan 26 '16 at 03:40
  • Hmmm... maybe you can evaluate that when the user enters the number. For example you can assign the value to a `float` then cast it to `int` and compare their values. – B. Kostas Jan 26 '16 at 03:46
  • If you call a function passing an int in the stack frame built fon function call it will be allocated space for a sequence of 32 bits. How to interpret those 32 bits inside the called function is up to you – mauro Jan 26 '16 at 03:53
  • 1
    Why are you passing a float to an arg of type int? Why not fix the problem at its root? – David Heffernan Jan 26 '16 at 05:40

2 Answers2

2

Once a floating point value has been converted to an integer there is nothing you can do at run-time to find out what the type of the actual parameter was. What you can do, however, is let the compiler issue a warning when foo is called with a floating point value.

Example:

/*test.c*/

void foo(int a)
{
}


int main(void)
{
    foo(3.14);
    return 0;
}

If you use GCC you can add the option -Wconversion:

$ gcc -Wconversion test.c
test.c: In function ‘main’:
test.c:10:9: warning: conversion to ‘int’ alters ‘double’ constant value [-Wfloat-conversion]
     foo(3.14);
         ^

Other compilers usually have a similar option.

August Karlstrom
  • 10,773
  • 7
  • 38
  • 60
0

Use _Generic() (C11) to distinguish what function is called.

void foo_i(int a) {
  ...
}

void foo_f(float f) {
  if (f < INT_MIN) Handle_OutOfRange(); 
  if (f >= INT_MAX+1.0f) Handle_OutOfRange(); 
  if ((int)f != f) Handle_OutOfRange(); 
  foo_i(f);
}

#define foo(X) _Generic((X), \
float: foo_f, \
int: foo_i
)(X)
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • What if the user passes in a string or a character? I mentioned float just as an example, but I'm looking for a solution with comprehensive coverage. Would I need a case for every concievable data type? How about structs? – Adam Jan 26 '16 at 03:55
  • 1
    @Adam You are creating a moving target by adding new requirements. Best to define the scope of your post in the beginning. IAC, simple extend `foo(X)` to include the types of interest. be they `double`, `char`, etc. Look into `default` with `_Generic` to handle groups of types. – chux - Reinstate Monica Jan 26 '16 at 04:00
  • If you want to know when the user passes a string, then you make sure there's a function prototype in scope before the call, and the compiler will complain about the type mismatch. It won't necessarily do that with a float-to-int conversion, but a `char *` to `int` conversion will not compile. – Jonathan Leffler Jan 26 '16 at 04:22
  • I think OP doesn't want to code two (or more) different functions (one for float, one for int, etc...). As far as I have understood he wants to code just one function. Inside this single function - regardless the function prototype - he want to determine the right data type by only looking at the data passed to the function. This is why he did mention Java's "instanceof" (used to check if an object is an instance of a given class). But... how can you say if (suppose) a sequence of 32 zeroes represent an integer = 0 rather than a sequence of four NULLs or whatever else? – mauro Jan 26 '16 at 05:13
  • @mauro OP can still use `_Generic()` and macro `foo()` and have it call 1 function `foo_t(value, type_identifyer)`. This can be done like `GP(X)` in [this code](http://codereview.stackexchange.com/q/115143/29485) or in other wasy. In any case, the coder still must write code per each type just like in [instanceof](http://stackoverflow.com/questions/7526817/use-of-instance-of-in-java) – chux - Reinstate Monica Jan 26 '16 at 14:46