c ++将void *转换为int错误
Posted
技术标签:
【中文标题】c ++将void *转换为int错误【英文标题】:c++ casting void* to int error 【发布时间】:2015-07-02 09:56:10 【问题描述】:我对 C/C++ 比较陌生,我正在尝试使用一个 C 库来定义数据结构 PDS 并提供访问数据的方法。
这是我用来访问它的函数:
pdsGetNext (PDS *pds,char **pKey,PDStype *pT,size_t *pS,void **pD);
它基本上返回元素的键,元素的类型,元素的大小和元素的实际数据。 void **pD
在文档中是这样描述的:“指向地址的指针,它获取实际元素。”。
我正在尝试将数据转换为“PDStype”所指示的适当类型。我在将数据转换为整数时遇到问题,这里是示例代码:
char *key = NULL;
PDS_TYPE type;
size_t size;
void *data = NULL;
float f;
pdsRewind(myPDS);
while (pdsGetNext(myPDS, &key, &type, &size, &data) == PDS_ERR_NONE)
switch (type)
case PDS_TYPE::PDS_I:
// this is integer
printf("INT: %d\n", *((int*)data));
printf("INT PRINTED AS STRING: %s\n", (int*)data);
printf("INT AS STRING: %s\n", (char*)data);
break;
case PDS_TYPE::PDS_PCH:
//this is null terminated string
printf("STRING: %s\n", (char*)data);
break;
default:
break;
整数的实际值为7,输出如下:
INT: 55
INT PRINTED AS STRING: 7
INT AS STRING: 7
在我看来,如果我像 void *ptr = (char*)malloc(sizeof(o))
那样分配了 void 指针,然后尝试将它转换为像 @ 987654326@
我的问题是:将其转换为 int 时我在这里做错了什么吗?据我了解,数据返回为void*
的原因是为了让人们能够以这种方式使用强制转换。
【问题讨论】:
55 是 '7' 在 ascii 表中的代码。也许你想用 atoi 代替? 如果输入void *
,为什么要转换为(char *)
?
我将转换为 (char *),因为最终我将使用 C++ CLI 中的代码制作一个 powershell 模块并将其与System::Object::String
一起使用。其他类型将以类似的方式使用。
C/C++
到底是什么?
printf("INT PRINTED AS STRING: %s\n", (int*)data);
这会调用未定义的行为,因为您使用了错误的格式,%s
需要 char*
【参考方案1】:
55 是 "7" 的 ascii 值。 http://www.asciitable.com/
在 C 中:
int a = atoi(data);
在 C++11 中:
int myint1 = std::stoi(data);
因为你在 C++ 中使用数据是一个 void* 做一个reinterpret_cast<char*>(data);
像这样:
int myint1 = std::stoi(reinterpret_cast<char*>(data));
在 C 中:
#include <stdio.h>
#include <stdlib.h>
int main()
// to get a void* like you
char *tmp = "7";
void *data = (void*)tmp;
// what is matter for you
int a = atoi((char*)data);
printf("a = %d\n", a);
return 0;
在 C++11 中:
include <iostream>
int main()
// to get a void* with "7" like you we could get the same with a std::string
char *tmp = new char [1]();
tmp[0] = '7';
void * data = reinterpret_cast<void*>(tmp);
// what is matter for you
int a = std::atoi(reinterpret_cast<char*>(data));
std::cout << "a = " << a << std::endl;
return 0;
【讨论】:
这给了我与之前基本相同的结果。那么有没有办法避免使用将 char* 转换为 int 的方法?我的印象是void*
的使用是为了提供一个可以转换为类型的通用对象。
如果你只做 reinterpret_cast 你会得到同样的结果。做 int myint1 = std::stoi(reinterpret_cast当您说“将 char* 转换为 int”时,您是在给出“未明确定义的规范”,因为 char* 旨在提供与 int 完全不同的语义。
当您“强制”转换时,您是在以不同的语义重新解释相同的位模式。当您“转换”一个值时,您正在将位模式更改为另一个尽可能保留语义的位模式。
现在,字符文字(和字符串文字)应该是“可读文本”:'7'
与 7
不同,7+2
是 9
,但 '7'+'2'
是 'e'
.
那是因为+是整数运算,'7'是53,'2'是48,101是'e'。
现在,您有一块内存,其中放置了值“7”(与整数 53 对应的位模式相同:内存本身与类型语义无关:它只包含 00110101),其地址为称为void*
。
现在,由于 printf
的工作方式,%d 需要 int,并使用数字语义,而 %s 需要 char* 并使用文本语义。
您作为第二个参数放置的所有内容都将根据这些规范进行读取。
在您的第一种情况下,您使用void*
,使用它,因为它是您遵循的int*
(通过粗心的*
)获得一个对应于00110101 的int 值,即53,并将其提供给printf将其视为数字,并将其转换为显示的文本(“53”)。
在您的第三种情况下,您将 void*
视为 char*
并将其交给 printf 读取它(因为 %s)作为“字符序列”,因此打印“7”。
在第二种情况下,您将一个 int* 交给 printf,它需要一个 char* (因为 %s,并且它是这样对待的),因此仍然给您“7”。
如果要将值"7"
(文本)转换为数字7
(整数),您必须使用类似atoi
的函数并使用“打印返回值(现在是整数)” %d”。使用 %s 会崩溃,因为 7
被视为 char* 几乎可以肯定是程序内存空间之外的地址
【讨论】:
我真的不想将char*
转换为int
。我实际上期待函数 pdsGetNext
返回指向 int 的 void 指针,但我想情况并非如此。以上是关于c ++将void *转换为int错误的主要内容,如果未能解决你的问题,请参考以下文章