C 尝试将双精度转换为字符时出错*

C 尝试将双精度转换为字符时出错*,c,C,我的项目是扫描一个地址空间(在我的例子中是0x00000000-0xFFFFFF,或0-(232)-1)来查找一个模式,并在数组中返回内存中找到该模式的位置(可以多次找到) 因为地址空间是32位,所以i是double,max是pow(2,32)(也是double) 我想保持I的原始值不变,这样我就可以用它来报告找到模式的位置(因为实际找到模式需要向前移动超过I的几个字节),所以我想用temp(声明为char*)来复制I的值。然后,在稍后的程序中,我将取消对temp的引用 double i, ma

我的项目是扫描一个地址空间(在我的例子中是0x00000000-0xFFFFFF,或0-(232)-1)来查找一个模式,并在数组中返回内存中找到该模式的位置(可以多次找到)

因为地址空间是32位,所以i是double,max是pow(2,32)(也是double)

我想保持I的原始值不变,这样我就可以用它来报告找到模式的位置(因为实际找到模式需要向前移动超过I的几个字节),所以我想用temp(声明为char*)来复制I的值。然后,在稍后的程序中,我将取消对temp的引用

double i, max = pow(2, 32);
char *temp;
for (i = 0; i < max; i++) 
{
   temp = (char *) i;       
   //some code involving *temp    
}
double i,max=pow(2,32);
字符*温度;
对于(i=0;i
我遇到的问题是不能将double转换为char*。int可以是;但是,由于地址空间是32位(而不是16位),我需要一个双精度,它正好足够表示2^32


我能做些什么吗

在C语言中,
double
float
并不是你想象的那样;该代码演示了:

#include <stdio.h>

typedef union _DI
{
    double d;
    int i;
} DI;

int main()
{
    DI di;
    di.d =  3.00;
    printf("%d\n", di.i);
    return 0;
}
#包括
类型定义联合体
{
双d;
int i;
}DI;
int main()
{
迪迪;
di.d=3.00;
printf(“%d\n”,di.i);
返回0;
}
在这种情况下,您将不会看到
3
的输出


一般来说,即使您可以读取其他进程的内存,您的策略也无法在任何现代操作系统上运行,因为虚拟内存(一个进程“看到”的地址空间不一定(事实上,它通常不)代表系统上的物理内存)。

啊,学校作业。那好吧

uint32_t i;
for ( i = 0; i < 0xFFFFFFFF; i++ )
{
    char *x = (char *)i;
    // Do magic here.
}

// Also, the above code skips on 0xFFFFFFFF itself, so magic that one address here.
// But if your pattern is longer than 1 byte, then it's not necessary
// (in fact, use something less than 0xFFFFFFFF in the above loop then)
uint32\u t i;
对于(i=0;i<0xFFFFFFFF;i++)
{
char*x=(char*)i;
//在这里施展魔法。
}
//此外,上面的代码跳过0xFFFFFF本身,所以这里只有一个地址。
//但是如果您的模式长度超过1字节,那么就没有必要了
//(事实上,在上面的循环中使用小于0xFFFFFF的值)

切勿使用浮点变量存储整数。浮点变量进行近似计算。在这种情况下,它正好起作用,因为整数足够小,但要知道这一点,您需要熟悉浮点在特定机器/编译器上的工作方式以及将使用的整数范围。另外,编写程序更难,程序也会更慢

C定义一个足够大的整数类型来存储指针:
uintpttr\u t
。您可以将指针投射到
uintpttr\t
并返回。在32位机器上,
uintpttr\t
将是32位类型,因此它最多只能存储232-1的值。要表示覆盖整个类型范围(包括第一个值和最后一个值)的循环,您不能使用带有递增变量的普通for循环,因为结束条件要求循环索引的值超出范围。如果你天真地写

uintptr_t i;
for (i = 0; i <= UINTPTR_MAX; i++) {
    unsigned char *temp = (unsigned char *)i;
    // ...
}
请注意,如果您能够做到这一点,用这种方式探索4GB将非常缓慢。每当您尝试访问未映射的地址时,都会出现分段错误。您可以使用信号处理程序处理segfault,但这很棘手而且很慢。你所尝试的可能不是老师所期望的,但它没有任何实际意义

要在Linux上探索进程的内存,请阅读
/proc/self/maps
,以发现其内存映射。有关Python中的一些示例代码,请参见


另外请注意,如果要查找模式,则需要考虑整个模式的长度,逐字节查找并不能完成全部工作。

双精度
转换为指针是违反约束的行为,因此会出现错误

浮动类型不得转换为任何指针类型。C11dr§6.5.4 4


要扫描整个32位地址空间,请使用具有[0…0xFFFFFFFF]范围的整数类型的
do
循环

uint32_t address = 0;
do {
  char *p = (char *) address;
  foo(p);
} while (address++ < 0xFFFFFFFF);
uint32\u t地址=0;
做{
char*p=(char*)地址;
富(p),;
}while(地址+++<0xFFFFFFFF);

您可以改用
uint32\u t
吗?而且,由于并非所有内存地址都可以访问,您几乎会立即遇到访问冲突(也称为“segfault”)另外,如果你希望在其他程序的内存中翻找,那是行不通的。每个进程只能看到自己的内存(加上一点共享内容)。除非你是在某个嵌入式系统上,或者是别的什么异国情调?@clunless\u c\u程序员-这很好,但是如果你一个字节一个字节地访问内存,你将在那里花费大部分时间。内存访问权限是按页面设置的(通常为4KB,但请向操作系统检查以确保安全)。如果你在一页上选错了,那么你可以安全地跳到下一页。不管怎样,你在使用什么操作系统,你想实现什么?这是一件奇怪的事情,而且很可能有更好的方法来完成您正在尝试的操作。C标准没有定义将
double
转换为指针,这是有充分理由的。对于你正在尝试做的事情来说,它只是一个错误的类型。正确的类型应该是
intptr\t
,如果存在的话。这将为您提供一个与指针宽度相同的整数类型。但是等等,为什么你甚至需要一个整数类型而不能通过指针进行迭代呢?还有一点是,访问不指向对象的指针是未定义的。。。哦,这里有很多错误。我的编译器(gcc)不喜欢uint32类型:错误:未知类型名称“uint32”我是不是忘记导入库了?@无知的程序员你需要
\include
才能使用
uint32\u t
。我尝试了完全实现上面的内容-循环永远不会结束。数字一直上升到0xFFFFFE,然后又从0开始。这是。。。古怪的它不应该那样做,因为
uint32_t address = 0;
do {
  char *p = (char *) address;
  foo(p);
} while (address++ < 0xFFFFFFFF);