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(data)); 第一种情况是 '7',即 53。在 void* 或 char* 中,第一种情况为字符 '7' 保留 53。我用您可以测试的测试代码完成了我的答案。第一行是用字符串“7”像你一样得到一个 void*。 好的。感谢您的解释和示例,非常感谢!【参考方案2】:

当您说“将 char* 转换为 int”时,您是在给出“未明确定义的规范”,因为 char* 旨在提供与 int 完全不同的语义。

当您“强制”转换时,您是在以不同的语义重新解释相同的位模式。当您“转换”一个值时,您正在将位模式更改为另一个尽可能保留语义的位模式。

现在,字符文字(和字符串文字)应该是“可读文本”:'7'7 不同,7+29,但 '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错误的主要内容,如果未能解决你的问题,请参考以下文章

将 char 转换为 int 的奇怪错误(目标 C)

将字符串转换为 int 时出现语法错误 [重复]

将字符串转换为 int 时出现语法错误

将 const void* 转换为 const int*

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

C#错误(无法将类型'string'隐式转换为'int')[重复]