深入理解C語言中編譯相關(guān)的常見錯(cuò)誤
更新時(shí)間:2013年05月22日 14:55:55 作者:
本篇文章是對(duì)C語言中編譯相關(guān)的常見錯(cuò)誤進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
1. /usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld 返回 1
Reason: no main function in source file
2. to get compile options -I and -l
pkg-config lib
e.g: pkg-config --cflags --libs dbus-1 glib-2.0 dbus-glib-1
gcc -o send-sms send-sms.c `pkg-config --cflags --libs dbus-1 glib-2.0 dbus-glib-1`
3. 如何讓pkg-config找到自己寫的庫
在庫中有一個(gè)文件libxxx.pc.in,其中會(huì)定義它所提供的頭文件在哪里,有哪些,其庫鏈接方式是怎么樣,庫在哪里,當(dāng)然這都是庫安裝到系統(tǒng)以后的信息,換句話說,可能對(duì)于編譯環(huán)境是無意義的。
prefix=@PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: library name
Description: description goes here
Requires: glib-2.0 gobject-2.0
Version: 0.1
Libs: -L${libdir} -llibrary_name
Cflags: -I${includedir}/some_sub_dir
這個(gè)文件定義了安裝后此庫的所有信息,而pkg-config就會(huì)讀取此信息。
4. forward declaration and incomplete type
出現(xiàn)這種錯(cuò)誤的時(shí)候通常是由于具體使用了某種類型,但此類型(到使用的時(shí)候)還僅有聲明,未有定義。比如說,某個(gè)頭文件有如下聲明:
#ifndef __POINT_H
#define__POINT_H
typedef struct _Point Point;
#endif
如果包含了此頭文件的文件,可以使用Point去聲明:
1).如聲明函數(shù)時(shí)的形式參數(shù),void print_point(Point p),注意是聲明函數(shù)時(shí),而不是定義函數(shù)
2). 聲明指針:Point *p;
但是不能使用Point去定義變量,
1). 如定義變量,Point p;
2). 定義函數(shù)時(shí)的形參,void print_point(Point p) { ... }
3) .或者為其指針申請(qǐng)內(nèi)在空間時(shí),Point *point = (Point *) calloc(1, sizeof(Point));
會(huì)報(bào)出incomplete type的編譯錯(cuò)誤。因?yàn)檫@個(gè)時(shí)候需要Notification所占的內(nèi)存大小和具體的定義形式,但是頭文件中并沒有給出具體的定義,所以編譯器不知道此類型所需要的內(nèi)存,所以會(huì)編譯出錯(cuò)。
C++中也是如此,為了效率會(huì)Forward declaration,也即在使用某個(gè)類前,不具體指定其類,而是聲明一個(gè)沒有定義的類:
class Point;
Point a;
使用Foward declaration時(shí),也只能用其去聲明,而不能具體使用此類型。
所以,如果要具體使用某個(gè)類型時(shí),其所包含的頭文件中必須要有類型的具體定義:
#ifndef __POINT_H
#define __POINT_H
typedef struct _Point Point;
struct _Point {
int x;
int y;
};
#endif
#include "point.h"
Point *n = (Point *) calloc(1, sizeof(Point));
n->x = 1;
n->y = 2;
....
其實(shí)原因也很簡單,當(dāng)令需要某個(gè)類型來聲明變量時(shí),不需分配內(nèi)存,不需要對(duì)其進(jìn)行操作,自然就不用了解其具體的類型定義。但當(dāng)你使用時(shí),要分配內(nèi)存時(shí),就必須要了解類型是怎么定義的,否則這些操作無法完成,這自然就需要知道類型的具體定義。
其實(shí),在頭文件中僅聲明類型的目的是為了信息隱藏,也就是不讓調(diào)用者知道這個(gè)類型具體的定義是什么樣子的,那么就需要像Java/C++中那樣去定義這個(gè)類型,
1) 把類型聲明為指針類型:
typedef struct Point *Point;
否則調(diào)用者還是有可能去定義。
2) 也即在頭文件的對(duì)應(yīng)源文件中封裝操作此類型的所有方法,這樣外界就沒有必要去了解類型是如何定義的了。它想操作時(shí),僅需要調(diào)用封裝的方法即可。
典型的實(shí)例:
頭文件point.h:
#ifndef __POINT_H
#define __POINT_H
typedef struct _Point *Point;
Point make_point();
void print_point(Point point);
void destroy_point(Point p);
#endif
實(shí)現(xiàn)源文件:point.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "point.h"
struct _Point {
int x;
int y;
};
Point make_point() {
Point point = (Point) calloc(1, sizeof(struct _Point));
point->x = 0;
point->y = 0;
return point;
}
void print_point(Point point) {
printf("point %d, %d\n", point->x, point->y);
}
void destroy_point(Point p) {
if (p == NULL) {
printf("warning, destroying NULL object");
return;
}
free(p);
}
(.text+0x18): undefined reference to `main'
collect2: ld 返回 1
Reason: no main function in source file
2. to get compile options -I and -l
pkg-config lib
e.g: pkg-config --cflags --libs dbus-1 glib-2.0 dbus-glib-1
gcc -o send-sms send-sms.c `pkg-config --cflags --libs dbus-1 glib-2.0 dbus-glib-1`
3. 如何讓pkg-config找到自己寫的庫
在庫中有一個(gè)文件libxxx.pc.in,其中會(huì)定義它所提供的頭文件在哪里,有哪些,其庫鏈接方式是怎么樣,庫在哪里,當(dāng)然這都是庫安裝到系統(tǒng)以后的信息,換句話說,可能對(duì)于編譯環(huán)境是無意義的。
復(fù)制代碼 代碼如下:
prefix=@PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: library name
Description: description goes here
Requires: glib-2.0 gobject-2.0
Version: 0.1
Libs: -L${libdir} -llibrary_name
Cflags: -I${includedir}/some_sub_dir
這個(gè)文件定義了安裝后此庫的所有信息,而pkg-config就會(huì)讀取此信息。
4. forward declaration and incomplete type
出現(xiàn)這種錯(cuò)誤的時(shí)候通常是由于具體使用了某種類型,但此類型(到使用的時(shí)候)還僅有聲明,未有定義。比如說,某個(gè)頭文件有如下聲明:
復(fù)制代碼 代碼如下:
#ifndef __POINT_H
#define__POINT_H
typedef struct _Point Point;
#endif
如果包含了此頭文件的文件,可以使用Point去聲明:
1).如聲明函數(shù)時(shí)的形式參數(shù),void print_point(Point p),注意是聲明函數(shù)時(shí),而不是定義函數(shù)
2). 聲明指針:Point *p;
但是不能使用Point去定義變量,
1). 如定義變量,Point p;
2). 定義函數(shù)時(shí)的形參,void print_point(Point p) { ... }
3) .或者為其指針申請(qǐng)內(nèi)在空間時(shí),Point *point = (Point *) calloc(1, sizeof(Point));
會(huì)報(bào)出incomplete type的編譯錯(cuò)誤。因?yàn)檫@個(gè)時(shí)候需要Notification所占的內(nèi)存大小和具體的定義形式,但是頭文件中并沒有給出具體的定義,所以編譯器不知道此類型所需要的內(nèi)存,所以會(huì)編譯出錯(cuò)。
C++中也是如此,為了效率會(huì)Forward declaration,也即在使用某個(gè)類前,不具體指定其類,而是聲明一個(gè)沒有定義的類:
class Point;
Point a;
使用Foward declaration時(shí),也只能用其去聲明,而不能具體使用此類型。
所以,如果要具體使用某個(gè)類型時(shí),其所包含的頭文件中必須要有類型的具體定義:
復(fù)制代碼 代碼如下:
#ifndef __POINT_H
#define __POINT_H
typedef struct _Point Point;
struct _Point {
int x;
int y;
};
#endif
#include "point.h"
Point *n = (Point *) calloc(1, sizeof(Point));
n->x = 1;
n->y = 2;
....
其實(shí)原因也很簡單,當(dāng)令需要某個(gè)類型來聲明變量時(shí),不需分配內(nèi)存,不需要對(duì)其進(jìn)行操作,自然就不用了解其具體的類型定義。但當(dāng)你使用時(shí),要分配內(nèi)存時(shí),就必須要了解類型是怎么定義的,否則這些操作無法完成,這自然就需要知道類型的具體定義。
其實(shí),在頭文件中僅聲明類型的目的是為了信息隱藏,也就是不讓調(diào)用者知道這個(gè)類型具體的定義是什么樣子的,那么就需要像Java/C++中那樣去定義這個(gè)類型,
1) 把類型聲明為指針類型:
typedef struct Point *Point;
否則調(diào)用者還是有可能去定義。
2) 也即在頭文件的對(duì)應(yīng)源文件中封裝操作此類型的所有方法,這樣外界就沒有必要去了解類型是如何定義的了。它想操作時(shí),僅需要調(diào)用封裝的方法即可。
典型的實(shí)例:
頭文件point.h:
復(fù)制代碼 代碼如下:
#ifndef __POINT_H
#define __POINT_H
typedef struct _Point *Point;
Point make_point();
void print_point(Point point);
void destroy_point(Point p);
#endif
實(shí)現(xiàn)源文件:point.c
復(fù)制代碼 代碼如下:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "point.h"
struct _Point {
int x;
int y;
};
Point make_point() {
Point point = (Point) calloc(1, sizeof(struct _Point));
point->x = 0;
point->y = 0;
return point;
}
void print_point(Point point) {
printf("point %d, %d\n", point->x, point->y);
}
void destroy_point(Point p) {
if (p == NULL) {
printf("warning, destroying NULL object");
return;
}
free(p);
}
相關(guān)文章
C++ std::condition_variable 條件變量用法解析
condition_variable(條件變量)是 C++11 中提供的一種多線程同步機(jī)制,它允許一個(gè)或多個(gè)線程等待另一個(gè)線程發(fā)出通知,以便能夠有效地進(jìn)行線程同步,這篇文章主要介紹了C++ std::condition_variable 條件變量用法,需要的朋友可以參考下2023-09-09詳解C語言中的錯(cuò)誤報(bào)告errno與其相關(guān)應(yīng)用方法
這篇文章主要介紹了C語言中的錯(cuò)誤報(bào)告errno與其相關(guān)應(yīng)用方法,包括errno和strerror以及perror的介紹,需要的朋友可以參考下2015-08-08c++ 對(duì)數(shù)器實(shí)現(xiàn)示例
對(duì)數(shù)器用于在自己的本地平臺(tái)驗(yàn)證算法正確性,本文詳細(xì)的介紹了c++ 對(duì)數(shù)器實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08C++解決業(yè)務(wù)辦理時(shí)間問題示例解析
這篇文章主要為大家介紹了C++解決業(yè)務(wù)辦理時(shí)間問題示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12C++實(shí)現(xiàn)LeetCode(9.驗(yàn)證回文數(shù)字)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(9.驗(yàn)證回文數(shù)字),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++項(xiàng)目基于HuffmanTree實(shí)現(xiàn)文件的壓縮與解壓縮功能
這篇文章主要介紹了C++項(xiàng)目基于HuffmanTree實(shí)現(xiàn)文件的壓縮與解壓縮功能,本文給大家提到文件壓縮的概念介紹及壓縮方法,通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08