2015-07-02 668 views
2

我对C/C++颇为陌生,我试图使用定义数据结构PDS并提供访问数据方法的C库。C++将void *转换为int错误

这里是我用来访问它的功能:

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 

它对我来说似乎是第一个,我想成为“7”,是什么打印出来,如果我打了空指针void *ptr = (char*)malloc(sizeof(o)),然后试图把它像int一样投给它像*((int*)ptr)

我的问题是:有东西将它转换为int时,我在这里做错了吗?据我所知,数据返回原因为void*是为了让一个人能够以这种方式使用转换。

+2

55之外几乎可以肯定地址为“7”在ASCII表的代码。也许你想用atoi代替? – AlexTheo

+0

为什么要输入'(char *)'如果输入'void *'? – Shreevardhan

+0

我铸造(字符*),因为最终我将使用代码在C++ CLI做出的PowerShell模块,并用'系统::对象:: String'使用它。其他类型将以相似的方式使用。 – user3141710

回答

0

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)); 

in 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; 
} 
+0

这给了我基本上与早前相同的结果。那么没有办法避免使用将char *转换为int的方法?我的印象是,使用'void *'是为了提供一个可以转换为类型的通用对象。 – user3141710

+0

如果你只做reinterpret_cast,你会得到相同的结果。做int myint1 = std :: stoi(reinterpret_cast (data)); –

+0

这是怎么回事?显示您尝试的代码 –

0

当你说 “转换一个char *为int” 你给人一种 “没有很好地界定规范”,因为字符*是为了服务于关于int的完全不同的语义。

当“强制”铸造,你重新诠释下,不同的语义相同的位模式。当你“转换”一个值时,你正在改变位模式到另一个保留语义尽可能。

现在,字符文字(和字符串)中的意思是“可读文本”:'7'是不一样的7,并7+29,但'7'+'2''e'

这是因为+是整数运算,和 '7' 是53, '2' 是48和101是 'E'。

现在,您有一块内存中的值'7'(即与整数53对应的相同位模式:内存本身与类型语义不可知的关系:它只包含00110101),其地址被称为void*

现在,由于printf的工作原理,%d需要int,并使用数字语义,而%s需要char *并使用文本语义。您将作为第二个参数

一切都将根据这些规范被读取。

在你的第一种情况下,你把void*,使用它,因为它是你的尊重(通过粗心*)获得相当于00110101是53 int值的int*,并给这对printf是把它当作一个数字,并将其转换为显示的文本(“53”)。

在第三种情况下,您将void*视为char*,并将其作为printf(由于%s)作为“字符序列”读取,因此会打印“7”。

在你的第二种情况下,你需要一个int *并将它提供给printf,因为它需要一个char *(因为%s,它会这样对待),因此仍然给你“7”。

如果要值"7"(文本)转换成数7(整数),你必须使用一个功能类似atoi并打印返回值(现在是一个整数)以“%d”。使用%s将crasch,因为7视为字符*是你的程序存储空间

+0

我真的不想将'char *'转换为'int'。我实际上期待函数'pdsGetNext'返回指向int的void指针,但我想不是这种情况。 – user3141710

相关问题