【问题标题】:Error C2040: 'void *()' differs in levels of indirection from 'int ()'错误 C2040:“void *()”的间接级别与“int ()”不同
【发布时间】:2013-02-18 00:42:32
【问题描述】:
#include <stdio.h>

main()
{
    myfunction();
}

void* myfunction() {
    char *p;
    *p = 0;
    return (void*) &p;
}

程序在 Visual Studio 上运行时,无法编译,错误信息如下:

“错误 2 错误 C2040: 'myfunction' : 'void *()' 在间接级别上与 'int ()' 不同”

有人可以简单解释一下吗?

谢谢!

【问题讨论】:

  • 虽然这不是您看到的错误,但您知道您的程序会因为您取消引用未初始化的内存位置而给您一个分段错误吗?变量char* p 未初始化,您正在尝试将值0 分配给存储在p 中的地址。
  • 您的意思是应该是 p=0,而不是 *p=0 吗?因为每个指针在使用前都必须初始化?
  • No *p = 0 是一个有效的语句,但它所做的是将p 指向的内存位置分配给0。由于指针p 未初始化,它指向的内存将是一些垃圾地址。所以你试图写入一些垃圾地址,这将导致segmentation fault
  • 初始化?比如 p = &something ?因此 p 然后设置为某个地址,而不是垃圾收集?谢谢!
  • 是的,完全是 p = &amp;someethingp = malloc(sizeof(char))

标签: c


【解决方案1】:

你应该在main()函数中使用它之前添加myfunction()的声明:

void* myfunction(void);

int main(void)
{
    myfunction();
    return 0;
}

void* myfunction(void) {
    char *p;
    *p = 0;
    return (void*) &p;
}

试试看。

【讨论】:

    【解决方案2】:

    您的程序有两个问题。第一个问题是Nan Xiao's answer 中提到的问题,编译器在看到您在main 中的调用时假设myfunction 的签名是int myfunction()

    第二个问题是myfunction 本身内部的间接级别不正确:

    void* myfunction(void) {
        char *p; // Create a pointer to a character
        *p = 0;  // Set some random location to zero
        return (void*) &p; // Take the address of the pointer to a character,
                           // and turn it into a pointer to anything
    }
    

    也就是说,你的演员正在使用 char ** 并用它制作 void *,这可能不是你想要的。

    如果要将字符指针转换为 void 指针,只需返回字符指针本身,不进行转换。

    【讨论】:

    • 对了,为什么说是“随机设置位置”呢?你能解释一下吗?在什么情况下不是随机的?谢谢
    • @user:因为你从来没有设置“p”指向什么,然后尝试写入它指向的任何东西。
    【解决方案3】:

    编辑:我误读了您的代码。答案已更新。

    正如@Nan Xiao 所说,您应该在调用 myfunction 之前声明它。我只能假设您的编译器错误地假设它存在并返回一个 int,这会导致稍后的投诉。

    我相信它抱怨该函数最初被“定义”为返回一个 int,但现在它找到了一个返回 void* 的函数。 int 有 0 个间接级别(它不是指针),而 void* 有一个(例如,它可以指向一个 int)。继续,void** 有两个间接级别(指向可以指向 int 的东西)。

    在 C 中,虽然您可以安全地将(比如说)double 转换为 int,但您不能在不解释如何操作的情况下将 int* 转换为 int(应该取消引用还是使用地址?)。

    【讨论】:

    • 确实有道理。非常感谢!
    • 另一个愚蠢的问题:“取消引用”是什么意思并使用地址?我的猜测是 *p 和 &p。不是吗?
    • 关闭。取消引用确实是 *p,但仅使用地址(我的术语;可能不是官方的!)就是说 (int) p,这将为您提供它作为整数指向的实际内存地址。因为编译器不知道你想做什么它会抛出一个错误。你必须明确告诉它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 2019-06-13
    • 2020-01-05
    • 1970-01-01
    • 2020-04-07
    相关资源
    最近更新 更多