分页: 1 / 2

[请教]关于linux下c语言(gcc)的语法与标准c不同的问题

发表于 : 2008-02-20 22:41
coolwdp
这是gcc的hello world:

#include <stdio.h>
int
main(void)
{
printf("Hello, world!\n");
return 0;
}
gcc编译无错通过
这是我写的 标准c上的筛质数程序:
zhishu2.c:

#include<stdio.h>

void main()

{int n,m,x,i,j;

printf("\n\nplease input min number:");

scanf("%d",&m);

printf("\n\nplease input max number:");

scanf("%d",&n);

if(m<=2&&n>=2) printf("2 ");

for(x=3;x<=n;x++)

{ j=0;

for(i=2;i<x;i++)

{

if(x%i!=0) j++;

if(j==x-2&&x>=m) printf("%d ",x);

}

}

printf("over\n");

}

编译有警告 zhishu2.c:3: 警告: ‘main’ 的返回类型不是 ‘int’
但还是通过了 并且执行通过了
请教一下 gcc的语法于标准c有何不同

:?:

发表于 : 2008-02-21 13:01
BigSnake.NET
因为你的不标准, 标准说明main必须返回int

发表于 : 2008-02-21 13:06
eexpress
gcc的strtof竟然要带-std=c99编译才正常。
我碰到过的。你也注意下。

发表于 : 2008-02-21 13:11
BigSnake.NET
eexpress 写了:
gcc的strtof竟然要带-std=c99编译才正常。
我碰到过的。你也注意下。
默认的是貌似是使用c89

man strtof

代码: 全选

       #define _XOPEN_SOURCE=600   /* or #define _ISOC99_SOURCE */

发表于 : 2008-02-21 13:14
eexpress
不是哦。我的total程序就是这样过来的。strtof是关键。

发表于 : 2008-02-21 14:04
RoyKing
标准C的main函数只有两种写法
1:

代码: 全选

int main() //main(int argc, char argv[])
{
    ... ...
    return 0;
}
2:

代码: 全选

main() //main(int argc, char argv[])
{
    ... ...
}

发表于 : 2008-02-21 14:32
bones7456
"Hello, world" example

The following simple application appeared in the first edition of K&R, and has become the model for an introductory program in most programming textbooks, regardless of programming language. The program prints out "hello, world" to the standard output, which is usually a terminal or screen display. Standard output might also be a file or some other hardware device, depending on how standard output is mapped at the time the program is executed.

代码: 全选

main()
{
    printf("hello, world\n");
}
The above program will compile on most modern compilers that are not in compliance mode, but does not meet the requirements of either C89 or C99. Compiling this program in C99 compliance mode will result in warning or error messages.[8] A compliant version of the above program follows:

代码: 全选

#include <stdio.h>

int main(void)
{
    printf("hello, world\n");
    return 0;
}

发表于 : 2008-02-21 22:37
coolwdp
那为什么不能直接定义main为空类型呢

发表于 : 2008-02-21 22:51
fredking
main 要return 给OS,返回值是有用的 ,不能为空

发表于 : 2008-02-22 13:24
BigSnake.NET
coolwdp 写了:那为什么不能直接定义main为空类型呢
没有为什么, 这是规定

发表于 : 2008-03-15 17:58
yang_hui1986527
RoyKing 写了:标准C的main函数只有两种写法
1:

代码: 全选

int main() //main(int argc, char argv[])
{
    ... ...
    return 0;
}
2:

代码: 全选

main() //main(int argc, char argv[])
{
    ... ...
}
当时学习的时候,是使用第二种的。
原来还有一种格式。呵呵

发表于 : 2008-03-15 18:59
linlee
void main()
好像是VC的~

发表于 : 2008-03-15 19:22
dbzhang800
C标准中从没有说过有 void main() 这种形式。

C语言标准 ISO/IEC 9899:1999(E) 第 5.1.2.2.1 节一开始就这样说:

代码: 全选

The function called at program startup is named main. The implementation declares no
prototype for this function. It shall be defined with a return type of int and with no
parameters:
        int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be
used, as they are local to the function in which they are declared):
        int main(int argc, char *argv[]) { /* ... */ }
or equivalent;9) or in some other implementation-defined manner.

发表于 : 2008-03-15 21:23
stlxv
yang_hui1986527 写了:
RoyKing 写了:标准C的main函数只有两种写法
1:

代码: 全选

int main() //main(int argc, char argv[])
{
    ... ...
    return 0;
}
2:

代码: 全选

main() //main(int argc, char argv[])
{
    ... ...
}
当时学习的时候,是使用第二种的。
原来还有一种格式。呵呵
第二种不对,现在的C标准不将int作为默认返回值,一定要加int

发表于 : 2008-03-21 23:23
yudaxia2
转载于http://bbs.xjtu.edu.cn/BMYFCDNGVVOVKBJEODGGKGEVBHWWPNWLQJHI_B/
----------------------------------------------------------------------------------------------------------------------------
1. main()函数的形式
先来说说main函数的定义,较早开始写C程序的肯定都用过这样的定义void main(){},其实翻翻C/C++标准,从来没有定义过void main()。
在C标准中main的定义只有两种:
int main(void)
int main(int argc, char *argv[])
在C++标准中main的定义也只有两种:
int main( )
int main(int argc, char *argv[])

换句话说:当你的程序不需要命令行参数的时候用int main(), 当需要命令行参数的时候请使用int main(int argc, char *argv[])

不过标准归标准,在不同的平台上,不同的编译器中对main()的定义方式总有自己的实现,比如早期编译器对void main()的支持(现在gcc也支持,不过会给出一个warning)。

特别的,因为历史的原因,在Unix-like平台上,大多还支持
int main(int argc, char *argv[], char *envp[])
其使用方式我们稍后再谈。

2. main()函数的返回
int main(...) 意味着需要return一个int值,如果不写,有的编译器会自动帮你添加一个return 0;,而有的则会返回一个随机值。为了避免不必要的问题,建议写的时候还是加上一个return 0;,浪费不了你多少时间,不是吗?
所以一个完整的test.c文件应该为:
int main(int argc, char *argv[])
{
return 0;
}
当然我们也可以尝试着让main返回一个long, double甚至是struct,更改main函数中的形参定义。这在有些编译器上是能编译通过的,不过可能会有一些警告(如GCC)。但是运行的时候如果编译器能做转换的还好,如返回long,float. 如果不能的话(如返回struct,或者main(int argc, char *argv0,char *argv1,char *argv2))会造成segmentation fault。


3. main()的调用和返回
在了解了main()函数的定义和返回形式后,我们再来看看main函数是怎么被调用的,它又"return"给了谁。在"gcc的编译过程"一中,我们回顾了程序从源码到可执行程序的过程,在"应用程序在linux上是如何被执行的"一文中,我们回顾了可执行文件怎么被操作系统加载的,今天我们继续这个过程。
上文提到不管是在load_elf_binary()中或者使用了动态链接库,最后都执行到了应用程序的入口。不过这个入口不是main.而是_start()。
执行
gcc -o test test.c
readelf -a test
可以看到test文件的Entry point address是0x80482e0,在往后看,这个地址是.text的地址(代码段的开始),也是_start()的地址。在_start()中又会调用__libc_start_main(),主要做一些程序的初始化工作,感兴趣的同学可以读读glibc中的源码,注释很清楚。然后主角登场了,在 __libc_start_main()中最后会调用
int result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);//这是Unix-like下main函数的调用方式,这下大家明白main函数中形参的由来了吧。
result中放着main函数的返回值,然后带着这个值退出。
exit (result);

注意:虽然main函数是一个特殊的函数,是程序运行的入口,但它毕竟也是一个函数,是可以被调用的。如:
int main()
{
if(...)
return 0;
main();
return 0;
}
不过要小心调用方式,和退出条件,避免无穷递归。

4. shell中执行程序
通过前几次和上面的分析,我们终于基本弄清了应用程序的执行过程,再回顾一遍: 在某个交互式shell中敲入./test, 此shell fork()/clone()出一个子进程,这个子进程执行

execve("./test",char * const argv[], char * const envp[])

execve加载./test,并把参数argv[],envp[]一步一步传递下去。加载了./test之后,从./test的入口开始执行,即ELF文件中的_start(),_start()调用__libc_start_main(),

最后到了main。

int main(int argc, char *argv[], char *envp[])

看着这个main的定义和execve相似吧,没错main中的参数都是execve一步步传递下来的。argc是命令行参数个数,argv[]存储着各个参数的指针(注意argv[0]通常是程序
名,argv[1]开始才是命令行参数。这是由shell设置的),envp[]存储着环境变量表。然而在标准C中只定义了int main(int argc, char *argv[]),所以unix-like平台也提供了全局变量environ指向环境变量表。
extern char **environ;
当然也可以用getenv和putenv来访问特定的环境变量。

对了,父shell还在wait()./test的结束呢,不错,test中main函数return的值,在被__libc_start_main() exit之后,终于被父shell抓住了,可以用$?访问。
如$> ./test
$> echo $?
可以得到test返回的值。这样,你就知道main()函数中return的意义,以及如何在shell中使用了吧。尽管可以return任何值,也建议用return 0来表示程序正常结束。这样别人用shell脚本调用你写的程序的时候,就可以$?等于0来判断你的程序是否正常执行了。

最后小结一下:
1. 避免使用void main(),尽量使用int main() 或者 int main(int argc, char *argv[])。
2. 在main的结尾记得 return int;, 最好用return 0;表示程序的正常结束。
3. main函数和普通函数一样也是能被调用的。
4. main return的值最终会返回给其调用者,如shell中执行的程序,可以在shell中用$?得到其返回值。
5. 在unix-like环境中,可以使用int main(int argc, char *argv[], char *envp[]), extern char **environ; , getenv()等方式来得到环境变量。
By Pthread
08.01.03



转载于http://bbs.xjtu.edu.cn/BMYFCDNGVVOVKBJEODGGKGEVBHWWPNWLQJHI_B/[/list]