有没有一种标准化的方法来获取C ++编译器中的字节大小?

时间:2010-09-26 17:56:56

标签: c++ compiler-construction c-preprocessor

我想知道是否有一些标准化的方法可以在预处理器阶段获取内存中的类型大小 - 所以在宏观形式中,sizeof()不会削减它。

如果他们的标准方法不是大多数IDE使用的传统方法吗?

是否还有其他人可以想到的方法来获取此类数据?

我想我可以做一个两阶段构建的东西,得到一个测试程序的输出并将它反馈回IDE,但这并不比#defining他们更容易。

思想?

编辑:

我只是希望能够用

交换代码
#ifdef / #endif

我认为IDE或底层编译器可能在某些宏下定义该信息是不是天真?当然,预处理器不会获得有关任何实际机器代码生成功能的信息,但是IDE和编译器会这样做,并且他们会调用预处理器并提前向其声明内容。

进一步编辑

我认为这是一个可以想象的概念:

C ++委员会有一个标准,对于每种类型(可能只有C ++本机),编译器必须向IDE提供一个头文件,默认情况下包含在内存中声明本机类型使用的内存大小,如这样:

#define CHAR_SIZE 8
#define INT_SIZE 32
#define SHORT_INT_SIZE 16
#define FLOAT_SIZE 32
// etc

这个过程中是否存在缺陷?

进一步编辑

为了解决多平台构建阶段问题,或许这个标准可能要求像lacqui所示的简单程序需要编译并运行默认运行,这样,无论什么类型获取size将是在第二个或“正常”构建阶段编译代码的同一台机器。

道歉:

我一直在使用'变量'代替'类型'

8 个答案:

答案 0 :(得分:3)

抱歉,预处理器阶段无法提供此信息。要计算变量的大小,您必须完成解析和抽象评估的所有工作 - 而不是完全代码生成,但您必须能够评估常量表达式并替换模板参数,例如。而且你必须比预处理器通常更了解代码生成目标。

我认为,两阶段构建的东西是大多数人在实践中所做的事情。有些IDE将整个编译器内置为库,这样可以让他们更有效地完成工作。

答案 1 :(得分:3)

根据您的构建环境,您可以编写一个实用程序来生成其他文件包含的标头:

int main(void) {
    out = make_header_file();  // defined by you
    fprintf(out, "#ifndef VARTYPES_H\n#define VARTYPES_H\n");

    size_t intsize = sizeof(int);
    if (intsize == 4)
        fprintf(out, "#define INTSIZE_32\n");
    else if (intsize == 8)
        fprintf(out, "#define INTSIZE_64\n");
    // .....
    else fprintf(out, "$define INTSIZE_UNKNOWN\n");
}

当然,请根据需要进行编辑。然后在需要这些定义的任何地方加入“vartypes.h”。

编辑:或者:

fprintf(out, "#define INTSIZE_%d\n", (sizeof(int) / 8));
fprintf(out, "#define INTSIZE %d\n", (sizeof(int) / 8));

请注意第二个缺少下划线 - 第一个创建INTSIZE_32,可以在#ifdef中使用。第二个创建INTSIZE,可以使用,例如char bits[INTSIZE];

警告:这仅适用于8位char。大多数现代家庭和服务器计算机将遵循这种模式;但是,某些计算机可能使用不同大小的char

答案 2 :(得分:3)

为什么你还需要这个?

The cstdint include提供描述所有标准整数类型的typedef#defines,包括typedef s用于精确宽度int类型和{{ 1}}表示它们的完整值范围。

答案 3 :(得分:2)

不,这是不可能的。例如,完全可以在一台机器上运行预处理器,并在完全不同的机器上完全单独进行编译,这些机器(可能)具有(至少某些)类型的不同大小。

对于一个具体的例子,考虑SQLite的正态分布是他们所谓的“合并” - 一个已经预处理的源代码文件,它实际上是在您的计算机上编译的。

答案 4 :(得分:2)

您想根据某种类型的尺寸生成不同的代码吗?也许你可以用模板专业化做到这一点:

#include <iostream>

template <int Tsize>
struct dosomething{
  void doit() { std::cout << "generic version" << std::endl; }
};

template <>
void dosomething<sizeof(int)>::doit()
{ std::cout << "int version" << std::endl; }

template <>
void dosomething<sizeof(char)>::doit()
{ std::cout << "char version" << std::endl; }


int main(int argc, char** argv)
{
  typedef int foo;
  dosomething<sizeof(foo)> myfoo;
  myfoo.doit();

}

答案 5 :(得分:1)

那怎么办?在预处理阶段不知道大小。那时,您只有源代码。找到类型大小的唯一方法是编译它的定义。

您可能还想要一种方法来获得在编译阶段运行程序的结果。答案是“你不能,你必须运行程序来获得它的输出”。就像你需要编译程序以获得编译器的输出一样。

你想做什么?

关于你的编辑,它似乎仍然很混乱。

对于内置的类型,可以想象这样的标题,但从不存在变量。也许可以编写一个宏来用硬编码的数字替换已知的类型名称,但如果你给它一个变量名,它就不知道该怎么做。

再一次,你想做什么?你试图解决的问题是什么?如果你给我们更多的背景,可能会有一个理智的解决方案。

答案 6 :(得分:1)

对于常见的构建环境,许多框架都是手动设置的。例如,

http://www.aoc.nrao.edu/php/tjuerges/ALMA/ACE-5.5.2/html/ace/Basic__Types_8h-source.html

定义ACE_SIZEOF_CHAR之类的内容。在我买的一本名为POSH的书中描述的另一个图书馆也以一种非常易于理解的方式做到了这一点:http://www.hookatooka.com/wpc/

答案 7 :(得分:0)

术语“标准化”是问题所在。没有标准的方法,但使用某种配置实用程序设置一些预处理器符号并不是很困难。一个真正简单的就是编译并运行一个小程序,用sizeof检查大小,然后输出一个带有一些符号集的包含文件。