2012-01-28 31 views
6

Tôi có sau "hằng số" tiêu đề:Linking vấn đề với "nhiều định nghĩa về" lỗi biên dịch

/* constants.h */ 

#ifdef __cplusplus 
extern "C" { 
#endif 

#pragma once 

#ifndef CONSTANTS_H 
#define CONSTANTS_H 

const char * kFoo = "foo"; 
const char * kBar = "bar"; 

#endif 

#ifdef __cplusplus 
} 
#endif 

Tôi #include -ing tiêu đề này trong các tập tin X.cY.c.

Lưu ý rằng tôi là không phải bao gồm điều này trong X.h hoặc Y.h.

Các tệp X.cY.c được biên dịch thành các tệp đối tượng được lưu trữ vào thư viện tĩnh được gọi là libXY.a.

Khi tôi bao gồm X.hY.h trong Z.h, và khi tôi liên kết đến libXY.a, tôi không thể biên dịch Z.c không có lỗi:

/* Z.h */ 

#include "X.h" 
#include "Y.h" 

tôi nhận được lỗi biên dịch sau khi cố gắng biên dịch Z.c:

/path/to/libXY.a(X.o):(.data+0x0): multiple definition of `kFoo` 
/path/to/libXY.a(Y.o):(.data+0x0): first defined here 
/path/to/libXY.a(X.o):(.data+0x8): multiple definition of `kBar` 
/path/to/libXY.a(Y.o):(.data+0x8): first defined here 

Tôi đã thử đặt kFookBar thành extern, nhưng điều đó không giúp được gì.

Làm cách nào để giải quyết nhiều định nghĩa, khi tôi chỉ bao gồm các hằng số một lần (thông qua bảo vệ tiêu đề #ifndef CONSTANTS_H)?

+0

Có lẽ không phải là vấn đề ngay lập tức (không chắc chắn), nhưng bạn nên loại bỏ bogus '#pragma once' và đặt các bộ bao gồm nhiều sự bao gồm thích hợp vào tiêu đề của bạn. Định dạng chuẩn là '#ifndef MYHEADER_H #define MYHEADER_H .... # endif' –

Trả lời

9

Làm thế nào tôi có thể giải quyết nhiều định nghĩa, khi tôi chỉ bao gồm các hằng số một lần (thông qua bảo vệ đầu trang #ifndef CONSTANTS_H)?

Với điều này trong constants.h:

const char * kFoo = "foo"; 

một định nghĩa cho kFoo sẽ được phát ra trong mỗi dịch mà #include s constants.h. Vì vậy, nhiều định nghĩa, sau đó dẫn đến lỗi liên kết.

Như asaelr lưu ý (1), bạn sẽ giải quyết nó như thế này:

constants.h

extern const char* const kFoo; 

hằng số.c

const char* const kFoo = "foo"; 

(lưu ý rằng tôi cũng đã const con trỏ, đó là thường những gì bạn muốn làm trong trường hợp này)

+4

Có một số tùy chọn khác có thể được xem xét. Trong bối cảnh hiện tại, những gì bạn đã đề xuất là đúng, nhưng: (A) 'static const char * kFoo =" foo ";' sẽ hoạt động mà không có một tập tin constants.c riêng biệt; và (B) 'static const char kFoo [] =" foo ";' có thể là một biểu hiện chính xác hơn về những gì cần thiết (và 4 hoặc 8 byte ít không gian được sử dụng, phụ thuộc vào con trỏ 32 bit so với 64 bit); và (C) 'extern const char kFoo [];' cộng với constants.c chứa 'const char kFoo [] =" foo ";' có thể là một biến thể thích hợp của giải pháp của bạn. Mã có lẽ không được phép thực hiện 'kFoo =" pqr ";'. –

+0

@JonathanLeffler +1 Tôi thực sự bắt đầu viết về các biến thể có thể được thực hiện trong trường hợp này trong chỉnh sửa tiếp theo, nhưng đã hủy các chỉnh sửa của tôi khi tôi và những người khác trên trang web này đã thực hiện điều đó. Tôi nghĩ rằng 'extern const char * const kFoo;' nói chung là cách rõ ràng nhất (bằng cách sử dụng C) để khai báo/tài liệu mà bạn đang đối phó với một hằng số chuỗi. Tất nhiên, đó là chủ quan. A + B) sẽ hoạt động, nhưng có thể dẫn đến sưng lên nhị phân. tiền tố constants.h + 'k' cho thấy đây là dự án osx hoặc ios (thường kết thúc trong pch). 'extern' thường đơn giản nhất để biên dịch và liên kết trong kịch bản đó. – justin

+0

Trừ khi bạn thực sự cần một con trỏ cũng như chuỗi, hãy sử dụng ký pháp mảng trong tùy chọn ký hiệu con trỏ. Tôi đồng ý rằng các phiên bản tĩnh có thể dẫn đến mã bloat và thường không được khuyến khích. (Các phiên bản con trỏ dẫn đến mã bloat, quá, tăng thực thi bởi kích thước của một con trỏ cho mỗi hằng số.) –

4

Bạn không nên xác định các biến trong tệp tiêu đề. xác định chúng trong một trong các tệp nguồn và khai báo chúng (extern) trong tệp tiêu đề.

(Bạn đã viết "Tôi đã cố gắng thiết lập kFoo và kbar để extern, nhưng điều đó không giúp đỡ." Tôi đoán rằng bạn đã không xác định chúng trong một file nguồn)

+0

Nếu tôi định nghĩa các biến trong' constants.c', tôi nhận được lỗi "tham chiếu không xác định đối với' kFoo' "khi biên dịch thư viện. (Tôi đang biên dịch 'hằng số.c' thành' hằng số'o' và bao gồm nó với thư viện.) Có suy nghĩ gì không? –

+0

Bạn đã xác định hoặc khai báo? Làm thế nào để bạn liên kết nó? – asaelr

Các vấn đề liên quan