定义非零整数的结构

时间:2016-03-31 20:23:52

标签: c types

假设我们想要定义整数除法以排除除零。有可能这样做吗?我想要的东西看起来像:

#include <stdio.h>
#include <assert.h>

/* Define a structure intn0. */
typedef struct intn0 intn0;

struct intn0{
    int x;
    /* assert(x != 0); */
};

int div(int a, intn0 b){
    return a / b.x;
};

显然,这不起作用。有没有办法在结构级别上执行这种断言,比如,为了定义除法函数,使得对于所有有效输入(即正确类型的输入),我们可以保证它将生成有效输出而不用错误,没有垃圾?

如果你不能在C中做到这一点,那么哪种语言允许这种抽象(最好是类似于C而不是像Haskell之类的东西)?

3 个答案:

答案 0 :(得分:2)

  

有没有办法在结构层面上执行这种断言,

如果使用不透明指针,则可以这样做。

.h文件:

// Declare the struct but don't define it in the .h file.
typedef struct intn0 intn0;

intn0* create_intn0(int val);

int get_value(intn0* intPtr);

.c文件:

#include "***.h" // Use an appropriate name for the .h file.

// Define the struct so that functions in the .c file can use it.
struct intn0 { int n; };

intn0* create_intn0(int val)
{
   assert(val != 0);
   intn0* intPtr = malloc(sizeof(*intPtr));
   assert(intPtr  != NULL);
   intPtr->n = val;
   return intPtr;
}

int get_value(intn0* intPtr)
{
   assert(intPtr != NULL);
   return intPtr->n;
}

答案 1 :(得分:2)

  

有没有办法在结构层面上执行这种断言,比如说,

断言与可执行代码对应(启用时)。您不能将断言嵌入到C中的数据结构中,尽管您可以使用Java或C ++(例如),通过使类的成员保持私有并保护所有设置它们的方法来使用测试有效性的代码(由类定义) )拟议价值。正如@RSahu所观察到的,你可以在C中做类似的事情,尽管该语言并没有提供实际强制执行的方法。

但是,在某些情况下,可以定义一个数据结构,该数据结构不代表您不希望它表示的值。例如:

/*
 * Represents a non-zero integer between -(UINT_MAX+1) and (UINT_MAX+1),
 * inclusive; has no representation for zero.
 */
struct intn0 {
    _Bool is_negative;
    unsigned n_less_one;
};
  

为了定义一个除法函数,使得对于所有有效输入(即正确类型的输入),我们可以保证它将生成一个有效的输出而没有错误且没有垃圾?

具有上述结构类型的整数除法可能如下所示:

int div(int a, struct intn0 b){
    return (b.is_negative ? -1 : 1) * (a / ((long long) b.n_less_one + 1));
};

假设类型long long足够大以表示UINT_MAX + 1,它将永远不会被除以零,并且将始终为每个可能的参数对产生一致且合理的结果。如果除法语义不完全符合您的要求,那么我相信您可以调整它们以适应它们。

答案 2 :(得分:1)

我认为这对C结构来说是一个合理的期望(没有它比它的价值更麻烦)。您可能会切换到C ++并编写自定义整数类,但您需要大量代码才能实现int(您can't inherit from int)的所有正常行为。

您最好的选择是定义自定义除法功能:

int zero_safe_div(int a, int b){

    if (b != 0)
        return a / b;
    else
         /* return zero or whatever behavior you want in this case */
}

由于您似乎对其他语言开放,您也可以使用Python,它允许您从int类型继承(因为它只是像Python中其他所有类一样的类):

class safe_div_int(int):
    def __init__(self, val):
        self.val = val
    def __div__(self, rhv):
        if rhv != 0:
            return self.val / rhv
        else:
            return 0 # this could be replaced with whatever behavior you want for the 
                     # zero division case

v1 = safe_div_int(3)

print("V1: {}".format(v1))
print("V1 / 5.0: {}".format(v1 / 5.0))
print("V1 + 5: {}".format(v1 + 5))
print("V1 / 0: {}".format(v1 / 0))

此代码生成此输出:

  

V1:3
  V1 / 5.0:0.6
  V1 + 5:8
  V1 / 0:0