免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 11919 | 回复: 0
打印 上一主题 下一主题

void value not ignored as it ought to be [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-12-18 11:49 |只看该作者 |倒序浏览

1.void value not ignored as it ought to be
不能在表达式中使用void函数的值,让这个函数单独成一行,然后再对其进行操作.

用GCC编译出现如下错误:   
  test9.c:17:   void   value   not   ignored   as   it   ought   to   be   
   
  程序是关于流的IO操作,代码如下:   
  ........   
  FILE   *stream;   
  if((stream=fopen("test","r"))==(FILE*)0)   
  {   
  fprintf(stderr,"error   opening   file.\n");   
  exit(1);   
  }   
  if((setlinebuf(stream))!=0)   //出错误的行   
  {   
  fprintf(stderr,"error   setlinebuffer.\n");   
  exit(1)   
  }   
  ..........   
   
  出错的意思好像是说setlinebuf不该加参数stream?弄不明白.....   
  请各位指点迷津!!
setlinebuf好像没有返回值,返回类型是void


undefined reference就是缺少类型定义,一般是少头文件。
链接期的 "undefined reference to" 不是少头文件,一般是该链接的 *.so *.a *.o 没有找到,可能是
没有,位置不对,配置原因导致命令行里缺少,甚至 Makefile 出错。
不是少头文件
但也应该不是找不到库或者目标文件,应该是找的到,但是那个库或目标文件里没有那个符号。
而没有那个符号的原因,要么是根本没有定义,要么是static的变量



出错消息是:undefined reference to'exp'
这不是标准库函数吗?怎么用不了?
解决答案是:gcc -lm filename.c
关于“undefined reference to”错误


       这两天在Linux下用Eclipse编数据结构,还有试用CPPUNIT,总是遇到一个错误,就是“undefined reference to [function name]”。找了很久,终于发现是在写makefile的疏忽所致。
出错的时候是这样的:
1 main:main.o Array.o
2     g++ main.o -o main
3     ./main
4 main.o:main.cpp Array.h
5     g++ -c main.cpp
6 Array.o: Array.cpp Array.h
7     g++ -c Array.cpp
后来才发现第二行编译的时候没有加上Array.o,把它加上就可以了。
1 main:main.o Array.o
2     g++ main.o Array.o -o main
3     ./main
4 main.o:main.cpp Array.h
5     g++ -c main.cpp
6 Array.o: Array.cpp Array.h
7     g++ -c Array.cpp
这个“undefined reference to ”一般是在找不到相应的库文件的时候产生的,没有加入Array.o也算是没有找到库文件的一种。有时可能需要在编译选项里加入"_lLIBNAME",来指定要加入的库文件。
"undefined reference to"怎么解决的?
有下面几个文件:
tiwei@tiwei-desktop:~/graph$ ls
binet.cpp global.cpp graph.cpp group.cpp main_1.cpp node_graph.cpp partition.cpp support.cpp
binet.hpp global.hpp graph.hpp group.hpp Makefile node_graph.hpp partition.hpp support.hpp
tiwei@tiwei-desktop:~/graph$
其中:
graph.cpp和partition.cpp引用了global.cpp中定义的GetNodeDict()函数,在
graph.cpp和partition.cpp中都使用了#include "global.hpp".
下面是我的Makefile文件:(我是改写别人的Makefile文件)
CC = g
CFLAGS = -g
INCLUDE = -I. -I/usr/include/ -I/usr/include/X11/ -I/usr/local/inclucde
LDFLAGS = -L. -L/usr/lib -L/usr/lib/X11 -L/usr/local/lib
LDLIBS = -L. -lprng -L/usr/lib -lm
SRCS = \
global.cpp graph.cpp group.cpp node_graph.cpp partition.cpp support.cpp \
main_1.cpp
OBJS = \
global.o graph.o group.o node_graph.o partition.o support.o main_1.o
.c.o:
$(CC) $(DEFS) $(INCLUDE) $(CFLAGS) -c $ , std::allocator  >, void*)'
graph.o: In function `graph::ClearAdjacencies()':graph.cpp:(.text 0x1df2): undefined reference to `GetNodeDict(std::basic_string , std::allocator  >, void*)'
partition.o: In function `partition::MapPartToNet(graph*)':partition.cpp:(.text 0x232f): undefined reference to `GetNodeDict(std::basic_string , std::allocator  >, void*)'
partition.o: In function `partition::partition(graph*, double, double, double, double, int, char, int, char, prng*)':partition.cpp:(.text 0x3da9): undefined reference to `GetNodeDict(std::basic_string , std::allocator  >, void*)'
partition.o: In function `partition::partition(graph*, double, double, double, double, int, char, int, char, prng*)':partition.cpp:(.text 0x58c3): undefined reference to `GetNodeDict(std::basic_string , std::allocator  >, void*)'
collect2: ld returned 1 exit status
make: *** [main] Error 1
tiwei@tiwei-desktop:~/graph$
网友回复:你的是GetNodeDict这个函数没定义,可能没包头文件之类的
网友回复:GetNodeDict这个函数在Global.cpp中定义了,在Global.hpp 也中声明了。
在graph.cpp和partition.cpp文件中也加了#include "global.hpp"语句了。
网友回复:GetNodeDict在graph.cpp和partition.cpp中声明了吗
网友回复:GetNodeDict函数在graph.cpp声明了,
在partition中没有,可是他们都是一样的错误啊?
是不是Makefile文件写错了啊?
网友回复:try as the following
OBJS = global.o graph.o group.o node_graph.o partition.o support.o main_1.o global.o graph.o group.o node_graph.o partition.o support.o main_1.o
网友回复:楼上的,请问为什么写两遍呢?
我试试看
网友回复:我试了,还是不行。
OBJS = global.o graph.o group.o node_graph.o partition.o support.o main_1.o global.o graph.o group.o node_graph.o partition.o support.o main_1.o
有好多的"multiple definition of"错误。
网友回复:楼主把代码贴点出来看看.
网友回复:在global.hpp中声明的函数
global.hpp文件
C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
extern node_graph *GetNodeDict(string label,void *dict);
在global.cpp中实现的代码
C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
// Find and return a given node by label
node_graph *GetNodDict(string label,void *dict)
{
    node_tree *temptnd = new node_tree;
    void *treend = NULL;
   
    temptnd->label(label);
    treend = tfind((void*)temptnd,&dict,
            NodeTreeLabelCompare);
    FreeNodeTree(temptnd);
    return treend ? (*(node_tree**)treend)->ref() : NULL;
}
在graph.hpp中包含的头文件
graph.hpp文件
C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
#include "global.hpp"
在graph.cpp中的一个成员函数用到的
C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
void graph::RewireAdjacencyByLabel()
{
    void *nodeDict = NULL;
    // map the nodes into a dictionary
    nodeDict = MakeLabelDict();
    node_list *adja = NULL;
    node_graph *p = _header;
    while( (p = p->next()) != NULL )
    {
        adja = p->neig();
        while((adja = adja->next()) != NULL)
        {
            string a;
            adja->ref(GetNodeDict(a,nodeDict));
            adja->node(adja->ref()->num());
        }
    }
    // Done
    FreeLabelDict(nodeDict);// 希奇,FreeLabelDict()函数也是和GetNodeDict()一样的,而这个就不出错?
   
    return;
   
}
graph.cpp中的
C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
void graph::ClearAdjacencies()
函数也是这样用的,
还有partition.cpp中也是这样用的。
就不知道为什么会出错。
谢谢!
undefined   reference   to   ‘itoa’是指没有找到对应   itoa   的函数,你去掉对应的   itoa   的引用就不会报这个错了。
加个库链接 -lc 或 -lm

链接期的"undefined reference to"问题又一解
今天拿到公司的一个程序,在本机(ubuntu8.04)编译了一下,编译起见是一堆的警告:" 警告: 不建议使用从字符串常量到‘char*’的转换",可以跳过去,但是到了链接期间,就又是可恶的 "undefined reference to"问题了,网上查了一些资料说是因为找不到 *.a/*.o 之类的库文件,或者是库文件里面没有相关的符号导致,但是我这程序原样复制到服务器里面,借给是可以编译的,而且提示错误的那个 .a 文件也是从服务器复制的,可以保证是一模一样的,但为什么本机编译就是不行呢?后来想到服务器是RHEL4,
gcc --version 的输出是: gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-8)
g++ --version 的输出是: g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)
而我本机的 gcc和g++确都是 4.2.3 的新版本,会不会是编译器的版本不兼容呢?看makefile里面用的是 g++ ,所以我先安装了 g++-3.4 ,然后把makefile里面的 PUBCC = g++ 改为 PUBCC = g++-3.4 ,再编译的时候发现编译期间的警告没了,但是链接还是照样报错;于是又卸载了 g++-3.4,换成了 g++-3.3,再编译的时候,居然是一切正常,和服务器上的表现一样了....
最后: 虽然是找到了 链接期的"undefined reference to"问题 的又一个答案,但个人对编译器的不兼容问题表示忧虑.

:) :) 鉴于本人在此走过弯路及探索,为了大家少走弯路,现小结一下移植(porting)的林林总总,供大家参考,不足之处还望前辈们多多指教。
以C code移植到symbian中为例:因原c程序功能所限,我在vc6中用向导生成了一个exe程序。
1。将原C程序的所有.C文件放到\src\目录下,将所有.h文件放到\inc\目录下
2。edit the mmp file. 首先,添加\EPOC32\INCLUDE\LIBC到systeminclude,即把c库include进去。其次,在SOUCE里添加各C文件。一定要把所用到的c文件都加进去,缺少会报好多错误,如undefined reference to错误.最后添加:library estlib.lib //这个库是支持标准c的,必须添加
STATICLIBRARY ecrt0.lib //这个是exe程序所需要的,它为exe提供E32Main()入口
3。在vc6下,将.C和.h文件导入。
4。修改原C程序的.h文件,在文件开始添加:
#ifdef __cplusplus
extern "C" {
#endif
在尾部添加:
#ifdef __cplusplus
}
#endif
大体结构如下:
#ifdef __cplusplus
extern "C" {
#endif
/*.....mycode..........*/
/* 这里主要是用extern声明一些函数或变量*/
#ifdef __cplusplus
}
#endif
5。在exe的cpp文件里要加上extern "C"{}
形如:extern "C"
{
/*要把在该C++中引用C文件里的头文件include进来
如:#include
#include
#include
#include
或者添加所用到的c中的函数的声明,用extern声明,如extern void f1()
此处extern可以通过编译,但是链接时还要链接原C库文件,不然就会出错:形如
test.o(.test+0x1f):test.cpp:undefined reference to 错误
*/

}
在C++代码中调用C的库文件,需加上extern "C",用来告知编译器:这是一个用C写成的库文件,请用C的方式连接他们。
Undefined reference to 错误:这类错误是在连接过程中出现的,可能有两种原因∶一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题.
一般情况下,ARM生成将比模拟器(wins)生成更加困难,并且通常在第一次尝试时gcc会产生额外编译器错误和警告,因为gcc在一般情况下比microsoft编译器更为严格。
答疑:(此处参考bruce文章)标准头文件都有类似以下的结构
#ifndef _TEST_H
#define _TEST_H
#ifdef __cplusplus
extern "C" {
#endif
/*...*/
#ifdef __cplusplus
}
#endif
#endif /* _TEST_H */
分析,头文件中的编译宏“#ifndef _TEST_H、#define _TEST_H、#endif” 的作用是防止该头文件被重复引用。
extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;
其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。
被extern "C"限定的函数或变量是extern 类型的;
extern 是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:
extern int a;
仅仅是一个变量的声明,其并不是在定义变量a,并未为a 分配内存空间(特别注意:实际上现在一般的编译器都会对上述语句作声明处理,但链接器在链接过程中如果没有发现该变量的定义,一般会在第一次遇到该变量声明的地方,自动定义)。变量a 在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern 声明。例如,如果模块B 欲引用该模块A 中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B 中调用模块A 中的函数时,在编译阶段,模块B 虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A 编译生成的目标代码中找到此函数。
与extern 对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
被extern "C"修饰的变量和函数是按照C 语言方式编译和连接的;
未加extern “C”声明时的编译方式首先看看C++中对类似C 的函数是怎样编译的。
作为一种面向对象的语言,C++支持函数重载,而过程式语言C 则不支持。函数被C++编译后在符号库中的名字与C 语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被C 编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int 之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,
生成的新名字称为“mangled name”)。
_foo_int_int 这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制
来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函
数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。
未加extern "C"声明时的连接方式
假设在C++中,模块A 的头文件如下:
// 模块A 头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
在模块B 中引用该函数:
// 模块B 实现文件 moduleB.cpp
#i nclude "moduleA.h"
foo(2,3);
实际上,在连接阶段,连接器会从模块A 生成的目标文件moduleA.obj 中寻找_foo_int_int 这样的符号!
加extern "C"声明后的编译和连接方式
加extern "C"声明后,模块A 的头文件变为:
// 模块A 头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif
在模块B 的实现文件中仍然调用foo( 2,3 ),其结果是:
(1)模块A 编译生成foo 的目标代码时,没有对其名字进行特殊处理,采用了C 语言的方式;
(2)连接器在为模块B 的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。
如果在模块A 中函数声明了foo 为extern "C"类型,而模块B 中包含的是extern int foo( int x, int y ) ,则模块B 找不到模块A 中的函数;反之亦然。
所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):
实现C++与C 及其它语言的混合编程。
明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧。
extern "C"的惯用法
(1)在C++中引用C 语言中的函数和变量,在包含C 语言头文件(假设为cExample.h)
时,需进行下列处理:
extern "C"
{
#i nclude "cExample.h"
}
而在C 语言的头文件中,对其外部函数只能指定为extern 类型,C 语言中不支持extern
"C"声明,在.c 文件中包含了extern "C"时会出现编译语法错误。
笔者编写的C++引用C 函数例子工程中包含的三个文件的源代码如下:
/* c 语言头文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif
/* c 语言实现文件:cExample.c */
#i nclude "cExample.h"
int add( int x, int y )
{
return x + y;
}
// c++实现文件,调用add:cppFile.cpp
extern "C"
{
#i nclude "cExample.h"
}
int main(int argc, char* argv[])
{
add(2,3);
return 0;
}
如果C++调用一个C 语言编写的.DLL 时,当包括.DLL 的头文件或声明接口函数时,应加
extern "C" { }。
(2)在C 中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C
语言中不能直接引用声明了extern "C"的该头文件,应该仅将C 文件中将C++中定义的extern
"C"函数声明为extern 类型。
笔者编写的C 引用C++函数例子工程中包含的三个文件的源代码如下:
//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif
//C++实现文件 cppExample.cpp
#i nclude "cppExample.h"
int add( int x, int y )
{
return x + y;
}
/* C 实现文件 cFile.c
/* 这样会编译出错:#i nclude "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 );
return 0;
}


我的报错:test.o(.test+0x1f):test.cpp:undefined reference to 错误
最终解决方法:
因为有的源程序的后缀写的不规范如“tlv320api.c”写成了“tlv320api.C”,而我编译时是直接采用*c进行编译的,编译器没有识别tlv320api.C。
arm-linux-uclibc-gcc -o test *.c -L/home/ksj/CUnitinstall/lib -lcunit -I/home/ksj/CUnitinstall/include

所以就报错了,另外,有的时候,把*h包含进来一起编译也会出现错误,所以,用什么就编译什么,还是比较稳妥!


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/78225/showart_1727539.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP