我可以根据某些计算结果定义类型吗?

时间:2010-07-13 23:18:15

标签: c++ c

我根据结果执行一些计算,我想对其余程序使用short int或int作为某种类型的数据。可以(/怎么可以)在C或C ++中明智地做到这一点?我并不真正关心使用的内存量(即2或4个字节),我的主要目的是访问通用数组,就像它们包含这种类型的数据一样。我想避免使用以下代码:

char s[128];
if (result of preliminary calculations was A)
  *((int*) s) = 50;
else
  *((short int*) s) = 50;

设置 s 的前4或2个字节。条件全局typedef是理想的:

if (result of preliminary calculations was A)
  typedef int mytype;
else 
  typedef short int mytype;

我不熟悉C ++类模板(还)。他们适用于我的问题吗?我是否必须在整个程序中更改声明(myclass<>和myclass<> *)?

非常感谢!

编辑:值可能并不总是对齐。即,int可以从第21位开始。感谢您的答案。

8 个答案:

答案 0 :(得分:4)

对于普通的C,你可以使用函数指针来完成这个:

static union { s_int[32]; s_short[64]; s_char[128]; } s;

static void set_s_int(int i, int n)
{
    s.s_int[i] = n;
}

static int get_s_int(int i)
{
    return s.s_int[i];
}

static void set_s_short(int i, int n)
{
    s.s_short[i] = n;
}

static int get_s_short(int i)
{
    return s.s_short[i];
}

static void (*set_s)(int, int);
static int (*get_s)(int);

根据初步计算设置一次:

if (result of preliminary calculations was A)
{
    set_s = set_s_int;
    get_s = get_s_int;
}
else
{
    set_s = set_s_short;
    get_s = get_s_short;
}

然后在程序的其余部分使用函数指针:

set_s(0, 50);   /* Set entry 0 in array to 50 */

您的文件编写功能可以直接引用ss.s_char,具体取决于其工作原理。

答案 1 :(得分:2)

在C和C ++中,所有类型信息都在编译时定义。所以不,你不能这样做。

答案 2 :(得分:2)

如果可以在编译时找到初步计算的结果,那么这可以工作。以下是一些简单的示例,以说明这是如何工作的。要执行更复杂的示例,请参阅http://en.wikipedia.org/wiki/Template_metaprogramming

using namespace std;
#include <iostream>

template<int x> struct OddOrEven    { typedef typename OddOrEven<x-2>::t t; };
template<>      struct OddOrEven<0> { typedef short t; };
template<>      struct OddOrEven<1> { typedef int t; };

template<bool makeMeAnInt> struct X       { typedef short t; };
template<>                 struct X<true> { typedef int t;   };

int main(void) {
  cout << sizeof(X<false>::t) << endl;
  cout << sizeof(X<true>::t) << endl;
  cout << sizeof(OddOrEven<0>::t) << endl;
  cout << sizeof(OddOrEven<1>::t) << endl;
  cout << sizeof(OddOrEven<2>::t) << endl;
  cout << sizeof(OddOrEven<3>::t) << endl;
  cout << sizeof(OddOrEven<4>::t) << endl;
  cout << sizeof(OddOrEven<5>::t) << endl;
}

我认为上面是标准的C ++,但如果没有,我可以告诉你这个关于g ++的工作(Debian 4.3.2-1.1)4.3.2

答案 3 :(得分:1)

您可以为此目的滥用模板。任何受决策影响的代码都必须根据int类型进行模板化。一个分支将实例化int版本,另一个分支将实例化short int版本。这可能是一个坏主意*。

修改

*嗯,将它应用于整体架构只是一个坏主意。如果您有一个封装了各种行为的特定数据类型,那么模板应该可以正常工作。

以下是Aaron McDaid回答的一个变体,用以说明它与条件的使用:

#include <iostream>
#include <string>
using namespace std;

template<int x> struct OddOrEven    { typedef typename OddOrEven<x-2>::t t; };
template<>      struct OddOrEven<0> { typedef short t; };
template<>      struct OddOrEven<1> { typedef int t; };

int main() {
    cout << "int or short? ";
    string which;
    cin >> which;

    if (which.compare("int") == 0)
        cout << sizeof(OddOrEven<1>::t) << endl;
    else if (which.compare("short") == 0)
        cout << sizeof(OddOrEven<0>::t) << endl;
    else
        cout << "Please answer with either int or short next time." << endl;

    return 0;
}

答案 4 :(得分:1)

我认为您的主要问题是,如果您不知道要阅读的类型,您计划稍后如何从s读取数据。

如果你有这个部分,你可以使用工会:

union myintegers
{
   int   ints[32];
   short shorts[64];
};

现在只需使用您想要的类型。

myintegers s;
if (result of preliminary calculations was A)
  s.ints[0] = 50;
else
  s.shorts[0] = 50;

更进一步,你可以将它全部包装在一个用result of preliminary calculations was A构造的类中,并覆盖运算符*和[]以存储在一个或另一个中。

但你确定要的吗?

答案 5 :(得分:1)

在当前的C ++标准(C ++ 03)中,你不能。

事实上你可以使用一些先进的元编程技巧,但它在大多数情况下都无济于事。

在下一个标准(C ++ 0x,最后肯定是C ++ 11)中,您将能够使用the keyword decltype来获取表达式的类型。如果您使用的是VC10(VS2010)或GCC 4.4或更新版本,那么您已经拥有该功能。

答案 6 :(得分:0)

这是我前一段时间项目的代码片段。

   void* m_pdata;
   if (e_data_type == eU8C1){
      pimage_data = new unsigned char[size_x * size_y];
   }
   if (e_data_type == eU16C1){
      pimage_data = new unsigned short[size_x * size_y];
   }

我希望它可以帮到你

答案 7 :(得分:0)

由于您声明的目标是将信息有效地存储在磁盘上,您应该学会停止直接将C / C ++数据结构的内存映像写入磁盘,而是序列化您的数据。然后,您可以使用多种形式的可变长度编码(“vlc”)中的任何一种来获得您想要的效果。最简单的是每字节7位的编码,其中第8位是连续标志,表示该值在下一个字节中继续。所以259将被存储为(二进制,其中连续位标记为间距和字节边界标记为;):

1 0000010 ; 0 0000011

或者,您可以使用头部半字节来表示将遵循的字节数,或者使用类似于UTF-8的方案,但开销略微增加,但更严格的重新同步保证。还有vlcs设计为可解析,并且在向前或向后读取时可以轻松地重新同步。