gpt4 book ai didi

c - 功能的可用性?

转载 作者:太空宇宙 更新时间:2023-11-04 05:05:20 25 4
gpt4 key购买 nike

我刚刚注意到在 C 中作为参数传递的函数在主函数中不再可用于直接调用。下面的代码编译产生错误

"../main.c:22:8: error: called object ‘hello’ is not a function or function pointer"

代码:
#include<stdio.h>

void hello(void)
{
printf("hello there\n");
}

void main(hello)
{
int y = 100;
printf("%i",y);

if (y==100)
hello();
}

是这样还是我做错了什么?

编辑:我将主要调用更改为 - void main(void hello (void))现在编译没有错误,但是在IF语句之后调用hello函数仍然没有执行printf语句。

EDIT NO 2:在阅读了很多答案后,我了解到我们可以将指向函数的指针作为参数传递给另一个函数。将整个函数作为参数传递是没有意义的。实际上,这整个困惑是由以下 opengl C 代码引起的,它显然在 Eclipse IDE 中运行成功:
#include <GL/glut.h>
#include<GL/gl.h>// Header File For The GLUT Library

void init(void)
{
glClearColor (0.0,0.0,0.4,0.0);
glShadeModel(GL_FLAT);
}

void reshape (int w, int h)
{
glViewport(0,0, (GLsizei) w, (GLsizei)h); // indicates the shape of the available screen area into which the scene is mapped
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10,10,-10,10,-10,10);


}

void display (void)
{
int i,j;

while(1){
for (i=-10; i <=10; i++){
glClearColor (0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_TRIANGLES);
glVertex3f(i,2,5);
glVertex3f(6,-i,-5);
glVertex3f(1,9,-1);
glEnd();
glFlush();}
}
}

int main (int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop ();
return 0;
}

在这里,如果您注意到调用 glutDisplayFunc(display) 显然将显示函数作为参数传递。这是怎么发生的?

最佳答案

你已经成功地模糊了事情。
void main(hello)声明 main (错误地)作为不返回任何内容并采用 int 类型的单个参数(隐式 int )。您不能调用 int ;因此您的局部变量隐藏了同名的外部函数。 C89 和准标准 C 允许“隐式 int ' 符号;它在 C99 或 C11 中是官方不允许的,尽管许多编译器会继续允许它,除非你要求他们发出警告。

你应该声明main()作为:

  • int main(void)
  • int main(int argc, char **argv)

  • Windows 确实允许 void main() ,很遗憾。 C++ 没有。

    如果您使用 GCC,请使用 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Wold-style-declaration 之类的选项进行编译(最好使用 -Werror )。并非所有版本的 GCC 都支持所有这些选项。使用您的版本支持的那些。

    顺便说一句,通过声明 hello作为 main() 的参数,您正在隐藏或隐藏 hello() 的外部定义功能。这是标准的 C 行为;在本地范围定义的名称隐藏在外部范围级别定义的具有相同名称的不同对象。您可以使用 -Wshadow当您遇到此问题时,GCC 的选项可以发现。

    后期编辑

    正如我已经问过的,您到底为什么认为启动环境会将指向函数的指针传递给您的 main()? ?

    函数定义:
    void main(void hello(void))

    仍然不匹配可接受的模式之一。

    此外,启动代码不会将指向函数的指针传递给您的 main()。 ;它基本上会调用你的代码,就好像你写了 int main(int argc, char **argv) (或可能 int main(int argc, char **argv, char **envp) )。保证不会将指向函数的指针传递给您的 main()。 .

    所以,无论发生什么,你都不会成功。通常, argc 的值(也许是 argv 的一部分)将被视为指向函数的指针(即使它不是)。所有的 hell 都会崩溃。

    简单定义:
    int main(void)

    并调用 hello()直接在 main() 的正文中.这就是所有有意义的事情。

    作为记录,这就是 GCC 关于问题中代码的说法(经修订):
    $ gcc -O3   -g   -I/Users/jleffler/inc   -std=c11   -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror   -Wshadow -c hello.c
    hello.c:3:6: error: no previous prototype for ‘hello’ [-Werror=missing-prototypes]
    void hello(void)
    ^
    hello.c:8:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
    void main(void hello (void))
    ^
    hello.c:8:6: error: first argument of ‘main’ should be ‘int’ [-Werror=main]
    hello.c:8:6: error: ‘main’ takes only zero or two arguments [-Werror=main]
    hello.c: In function ‘main’:
    hello.c:8:16: error: declaration of ‘hello’ shadows a global declaration [-Werror=shadow]
    void main(void hello (void))
    ^
    hello.c:3:6: error: shadowed declaration is here [-Werror=shadow]
    void hello(void)
    ^
    cc1: all warnings being treated as errors
    $

    将指针传递给函数——OpenGL 代码

    您可以将指向函数的指针作为参数传递给任何需要此类参数的函数。但是, main()是您无法修改的功能之一(标准 C 库中的功能也应视为“无法更改”;同上您使用的平台的操作系统接口(interface))。

    在您的 OpenGL 示例代码中,传递像 display 这样的函数指针是完全合法的。或 reshapeglutDisplayFunc()glutReshapeFunc()函数,因为它们被设计为接受指向函数的指针。您是否将您的初始产品写为:
    #include <stdio.h>

    static void hello(void)
    {
    printf("hello there\n");
    }

    static void invoke(void (*function)(void))
    {
    printf("-->> %s:\n", __func__);
    function(); // Or (*function)();
    printf("<<-- %s\n", __func__);
    }

    int main(void)
    {
    int y = 100;
    printf("%i\n", y);

    if (y == 100)
    invoke(hello);
    return 0;
    }

    不会有任何人的强烈抗议——编译器或人类。这是有助于理解函数指针的干净(C99 或 C11)代码。如果你写 void invoke(void function(void))如果没有显式指针,编译器会自动将类型转换为 '指向不带参数且不返回值的函数的指针 — 即 void (*function)(void) .因此,如果您愿意,您可以这样写,尽管我更喜欢显式指针表示法,尤其是因为在函数内部或作为全局变量,您必须使用显式指针表示法,因此将其与函数参数一起使用是一致的。在函数内部,编写:
    void function(void);

    声明一个函数,而不是指向函数变量的指针;必须写成:
    void (*function)(void) = hello;  // Note no parentheses on hello!

    与文件范围内的变量类似。因此,使用 void (*function)(void)函数参数列表(在原型(prototype)和定义中)中的表示法与语言的其余部分一致,因此是更好的表示法。

    关于c - 功能的可用性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23002138/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com