C++ const void* 转换

Posted

技术标签:

【中文标题】C++ const void* 转换【英文标题】:C++ const void* conversion 【发布时间】:2009-11-04 20:10:59 【问题描述】:

我正在尝试将三个参数传递给我的 write() 函数:

write(fd, "C,1,1\r\n", 7);

这很好用。但我想取一个参数并将其传递给命令部分以使其动态:

write(fd, N, 4);

我不熟悉 c++ 类型,但它一直要求一种“const void*”类型,我已经能够将我的变量 N 转换为几种不同的格式,希望其中一种更容易转换。这是我尝试过的:

const fmx::FixPt&  outValue = dataVect.AtAsNumber(3);
const double  N = outValue.AsLong();

double  N = outValue.AsLong();

所以 double 和 const double(*这可能几乎是一回事...我不太了解 c++)

我也可以保持原样:

const fmx::FixPt&  outValue = dataVect.AtAsNumber(3);
write(fd, outValue, 4);

但我认为询问每个人如何转换双精度值比试图解释或找出像 type const fmx::FixPt&... 这样独特的东西要好得多...

*我也试过了:

write(fd, &N, 4);

这只是摆脱了我的错误,但仍然不起作用。

那么,是否甚至可以转换为“const void*”类型?

非常感谢!

代码如下:

const fmx::FixPt& outValue = dataVect.AtAsNumber(3);
double  N = outValue.AsLong();

int fd;
struct termios options;
fd=open("/dev/tty.KeySerial1", O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, 0);
tcgetattr(fd,&options);
options.c_ispeed=57600;
options.c_ospeed=57600;
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_cflag &= ~CSTOPB;
options.c_lflag &= ~ECHO;
options.c_oflag &= ~ECHO;
options.c_oflag &= ~OPOST;
options.c_cflag |= CS8;
options.c_cflag |= CRTSCTS;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] =10;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&options);


if( tempText->Assign("2"), *tempText == direction ) 
    write(fd, "C,1,2\r\n", 7);//Direction
else
    write(fd, "C,1,1\r\n", 7);//Direction


if( tempText->Assign("1"), *tempText == speed ) 
    write(fd, "C,2,1\r\n", 7);//Speed
 else if( tempText->Assign("2"), *tempText == speed ) 
    write(fd, "C,2,2\r\n", 7);//Speed
 else if( tempText->Assign("3"), *tempText == speed ) 
    write(fd, "C,2,3\r\n", 7);//Speed
 else if( tempText->Assign("4"), *tempText == speed ) 
    write(fd, "C,2,4\r\n", 7);//Speed
 else if( tempText->Assign("5"), *tempText == speed ) 
    write(fd, "C,2,5\r\n", 7);//Speed
 else if( tempText->Assign("6"), *tempText == speed ) 
    write(fd, "C,2,6\r\n", 7);//Speed
 else if( tempText->Assign("7"), *tempText == speed ) 
    write(fd, "C,2,7\r\n", 7);//Speed
 else if( tempText->Assign("8"), *tempText == speed ) 
    write(fd, "C,2,8\r\n", 7);//Speed
 else if( tempText->Assign("9"), *tempText == speed ) 
    write(fd, "C,2,9\r\n", 7);//Speed
 else if( tempText->Assign("10"), *tempText == speed ) 
    write(fd, "C,2,10\r\n", 8);//Speed
 else if( tempText->Assign("11"), *tempText == speed ) 
    write(fd, "C,2,11\r\n", 8);//Speed
 else if( tempText->Assign("12"), *tempText == speed ) 
    write(fd, "C,2,12\r\n", 8);//Speed
 else if( tempText->Assign("13"), *tempText == speed ) 
    write(fd, "C,2,13\r\n", 8);//Speed
 else if( tempText->Assign("14"), *tempText == speed ) 
    write(fd, "C,2,14\r\n", 8);//Speed
 else if( tempText->Assign("15"), *tempText == speed ) 
    write(fd, "C,2,15\r\n", 8);//Speed
 else if( tempText->Assign("16"), *tempText == speed ) 
    write(fd, "C,2,16\r\n", 8);//Speed
 else if( tempText->Assign("17"), *tempText == speed ) 
    write(fd, "C,2,17\r\n", 8);//Speed




if(tempText->Assign("1"), *tempText == length)
    write(fd, "C,3,", 4);
    write(fd, "1", 1);
    write(fd, "\r\n", 2);
 else if(tempText->Assign("2"), *tempText == length)
    write(fd, "C,3,", 4);
    write(fd, "10", 2);
    write(fd, "\r\n", 2);
 else if(tempText->Assign("3"), *tempText == length)
    write(fd, "C,3,", 4);
    write(fd, "100", 3);
    write(fd, "\r\n", 2);
 else if(tempText->Assign("4"), *tempText == length)

    write(fd, "C,3,", 4);
    write(fd, N, 4);
    write(fd, "\r\n", 2);



close(fd);

错误:无法将参数 '2' 的 'double' 转换为 'const void*' 到 'ssize_t write(int, const void*, size_t)'

【问题讨论】:

你到底想做什么?从你写的内容很难判断,答案可能会有所不同,具体取决于你的最终目标。 请注意倒数第三行:“这只会消除我的错误,但仍然无法正常工作”。你是什​​么意思“不起作用”?你想完成什么? 对不起大家,有时我觉得如果我提供太多信息就会混淆问题。我正在为 FileMaker 编写一个插件,它将打开一个串行端口并将命令发送到跟踪设备,如 C、7 C、1、1 等......除了我需要命令 C、3、X 之外,一切正常取一个 1-10000 的数字。我想把那个号码传给它。在我只是硬编码“3000”或其他但我需要传递变量之前。当我编译它给我我的转换错误但是当我添加“&”时没有错误但是当我运行脚本时跟踪/扫描设备什么都不做。 【参考方案1】:

write 命令只获取一个数据块并写入文件描述符。因此,如果您想写入 double 中保存的二进制数据,您可以执行以下操作:

write(fd, &N, sizeof(double));

请注意,这会将 二进制 数据而不是人类可读的 ASCII 数据写入文件描述符。这可能很危险,因为数据以本地架构的字节顺序存储,但根据您的应用程序,这可能不是问题。

通常,在 C++ 中,您会使用 iostream 运算符:

double N = 0.0;

// write data to file
ofstream out("myfile", ofstream::binary);
out << N;
out.close();

// read data back
ifstream in("myfile", ifstream::binary);
in >> N;
in.close();

流操作符被重载以接受多种参数,包括字符串:

out << "hello world: " << 42 << endl;

【讨论】:

【参考方案2】:

在我看来,您的问题似乎是从双精度数转换为字符串。我认为,如果 N 的值为 2000,则您要写出字符“2”、“0”、“0”和“0”,而不是 2000.0 的内部表示。

实际上,我看到你使用了一个函数 outValue.AsLong(),我希望它返回一个 long 值(它是一个整数)而不是一个 double 值(它是浮点数),它会在这种情况下处理整数会更方便。在这种情况下,doublelong 是数据类型。

在 C 中将数字转换为字符串有点尴尬,通常使用 sprintf() 函数完成。这有点棘手。首先,您必须指定一个 char 数组以将字符串写入其中。确保它对于您将拥有的最大数字足够大,并添加一个,因为sprintf() 再写入一个字符来标记字符串的结尾。 (大多数 C 字符串函数都可以。)然后用它调用 sprintf。让我们来看看这个。

char string_value[5];  /* we're assuming the number is always between 0 and 9999 */
long long_value = outValue.asLong();
sprintf(string_value, "%04ld", long_value);
write (fd, string_value, 4);

解释其中一些:我们使用 5 个字符表示 string_value,因为我们需要字符数加 1。我们将值放入 long_value,然后使用 sprintf() 函数将值放入字符串值。 sprintf()的第一个参数是结果所在的内存区域,第二个是格式字符串,下面是你要放入字符串的值。在格式字符串中,'%' 表示它将描述一个字段,'0' 表示将结果填充为零,'4' 表示使用至少四个字符,而“ld”表示你是传入long 值。

【讨论】:

【参考方案3】:

write() 函数的第二个参数是指向缓冲区(字节数组)的指针,第三个参数是该缓冲区的大小。因此,您需要以某种方式获取要写入该文件的字节数组。

你的“解决方案”

write(fd, &N, 4);

如果 N 是 4 个字节长的东西,它将起作用。但是,这似乎不是您想要的。

从您的问题中不清楚您到底要完成什么。你想写一个字符串吗?然后你需要将 N 转换为一个字符串,并将该字符串的第一个字节的地址传递给write

【讨论】:

谢谢,对不起,我应该添加更多信息。我有一个 if/else if 语句正在检查长度: ... else if(tempText->Assign("4"), tempText == length) ... 所以我知道 4 是正确的(I 'm pass 1000) 我的工作示例: write(fd, "C,1,1\r\n", 7);它在我看来确实像一个字符串,但它一直说“无法将_____转换为'const void”为什么它要求'const void*'它看起来像一个字符串... 旁注,我试着做 const void tester = "1000";它起作用了......所以'const void *?再次感谢! 在 C 中,字符串指针,如 "C,1,1,\r\n"(类型为 const char *)将自动转换为 void *。但是在 C++ 中,您需要使用 (const void *)"C,1,1,\r\n" 显式转换。请注意,在像这样投射之前,您仍然必须以您想要的格式获得它! 而在 C++ 中,您真的很想执行 static_cast&lt;const void*&gt;(data),而不是 C 样式的强制转换操作。 @jheddings reinterpret_cast(data) 实际上,不是 static_cast。【参考方案4】:

从您的工作示例中,看起来 write 将 const char* 作为第二个参数,将长度(const char* 中的字符数)作为第三个参数。

所以write(fd, "C,1,1\r\n", 7); 正在传递一个指向“C,1,1\r\n”的 const char*,它有 7 个字符长。

如果您想传入一个变量而不是硬编码的“C,1,1\r\n”,那么您需要执行以下操作:

int someNum = 7; // example variable

const int BUFFERSIZE = 256;
char strBuffer[BUFFERSIZE];
snprintf( strBuffer, BUFFERSIZE, "whatever you like, even a number: %d\n\r", someNum );
write( fd, str, BUFFERSIZE );

【讨论】:

请记住,_snprintf_s() 不是标准函数。它存在于 Visual C++ 中,据我所知,在其他任何地方都没有。如果您使用任何其他编译器,则需要使用 sprintf() 或该编译器的特定函数。如果您使用 Visual C++,_snprintf_s() 比 sprintf() 更安全。 谢谢大卫,我已经用便携式安全版本的 sprintf 更新了示例。

以上是关于C++ const void* 转换的主要内容,如果未能解决你的问题,请参考以下文章

C ++:将void *转换为基类指针时访问冲突

void Test::printxy(void)' : 不能在 const 类中将 'this' 指针从 'const Test' 转换为 'Test &'

qsort 给出 [错误]:从 `int (*)(cricketer*, cricketer*)' 到 `int (*)(const void*, const void*)' 的无效转换

如何将 const void* 转换为 unsigned int?

在 C++ 中将非 const 转换为 const

如何将 const void* 强制转换为结构元素?