2010-07-20 56 views
14

Tại sao có sự khác biệt về đầu ra được tạo ra khi mã được biên dịch bằng cách sử dụng hai trình biên dịch gccturbo c.Sự khác biệt đầu ra trong gcc và turbo C

#include <stdio.h> 

int main() 
{  
    char *p = "I am a string"; 
    char *q = "I am a string"; 

    if(p==q) 
    { 
     printf("Optimized"); 
    } 
    else{ 
     printf("Change your compiler"); 
    } 
    return 0; 
} 

tôi nhận được "Optimized" trên gcc"Change your compiler" trên turbo c. Tại sao?

+27

Lấy gợi ý; sử dụng gcc ;-) – Amarghosh

+1

Thấy rằng các câu trả lời của câu hỏi của bạn đã được bao gồm trong chuỗi 'printf' (BTW có' \ n' thiếu ở đó) Tôi cho rằng bạn đã lấy ví dụ mã này từ đâu đó? Đây có phải là bài tập về nhà không? –

+1

FWIW, nếu bạn đang nói về trình biên dịch cổ từ Borland, tôi nghĩ rằng nó có một tùy chọn dòng lệnh ('-d') để kết hợp các hằng số chuỗi. – msandiford

Trả lời

33

Câu hỏi của bạn đã được gắn thẻ C cũng như C++. Vì vậy, tôi sẽ trả lời cho cả hai ngôn ngữ.

[C]

Từ ISO C99 (Section 6.4.5/6)

It is unspecified whether these arrays are distinct provided their elements have the appropriate values.

Điều đó có nghĩa là nó unspecified liệu pq được trỏ đến cùng một chuỗi đen hay không. Trong trường hợp của gcc cả hai đều trỏ đến "I am a string" (gcc tối ưu hóa mã của bạn) trong khi ở turbo c thì không.

Unspeci fi ed Hành vi: Sử dụng một giá trị unspeci fi ed, hoặc hành vi khác mà tiêu chuẩn quốc tế này cung cấp hai hay nhiều khả năng và áp đặt không yêu cầu thêm vào đó được chọn trong bất kỳ dụ


[C++]

Từ ISO C++ - 98 (Section 2.13.4/2)

Whether all string literals are distinct(that is, are stored in non overlapping objects) is implementation defined.

Trong C++, mã của bạn sẽ gọi hành vi được xác định.

thi-de fi Behavior ned: Unspeci fi ed hành vi mà mỗi thực hiện documents như thế nào lựa chọn được thực hiện


Xem thêm this câu hỏi.

+7

+1 vì đã báo cáo ý nghĩa chủ quan được xác định theo tiêu chuẩn của hành vi "không xác định"/"triển khai đã xác định". – ShinTakezou

+6

+1 cho câu trả lời rất kỹ lưỡng! –

+0

Cảm ơn bạn @Shin và @Amardeep :) –

15

Vì chuỗi ký tự của bạn là một biểu thức không đổi, tức là bạn không nên sửa đổi nó thông qua một con trỏ, không có mục đích thực sự để lưu trữ nó trong không gian bộ nhớ hai lần. Là một trình biên dịch mới hơn, gcc hợp nhất các chữ theo mặc định trong khi Turbo C thì không. Đây là dấu hiệu của sự hỗ trợ của gcc cho tiêu chuẩn ngôn ngữ mới hơn có khái niệm về dữ liệu const.

+2

Bạn có thể ghi đè hành vi này trong gcc bằng cách chuyển tùy chọn '-fno-merge-constants', mặc dù thường không có lý do chính đáng để làm như vậy. – Hasturkun

+0

@ Hasturkun: Mẹo hay :) @Amardeep: Câu trả lời rất hay! –

+1

@Amardeep, câu trả lời của bạn không hoàn toàn chính xác. Một chuỗi ký tự không phải là một biểu thức liên tục, nếu không nó sẽ không thể gán nó vào một 'char *'. Đó là sự thật, rằng một * nên * không thay đổi nó sau đó bằng cách truy cập thông qua con trỏ, nhưng nó được cho phép. Hành vi này chỉ là không xác định ... Trong mọi trường hợp, tôi không hiểu mọi người đưa ra các bài tập như thể hiện những thói quen xấu như vậy. Điều này luôn luôn phải là 'char const *' mà địa chỉ như vậy của một chuỗi ký tự được gán. –

1

Trình biên dịch có thể lưu giữ hai bản sao của các chữ giống hệt nhau nếu nó phù hợp. Tìm ra nếu đó là trường hợp có lẽ là điểm của chương trình này.

Trong những ngày cũ tốt, người lắp ráp giữ tất cả các chữ trong một hồ bơi theo nghĩa đen và vá hồ bơi theo nghĩa đen là một kỹ thuật sửa đổi 'hằng số' trong suốt chương trình.

Nếu một số cơ hội trình biên dịch cho phép trong trường hợp này là *p = 'H'; thì những khác biệt quan trọng trong hành vi sẽ dẫn đến.

+0

Cần phải nói rằng, trong nhiều phiên bản đầu tiên (trước ANSI) của C, việc sửa đổi các chuỗi ký tự được cho phép. – JeremyP

+0

@JeremyP: Xác định "Được phép". Tôi khá chắc chắn rằng nó luôn luôn là hành vi không xác định (một hệ thống nhúng có thể đặt chuỗi đó trong ROM) (mặc dù về mặt kỹ thuật, pre-ANSI, everytihng đã được chính thức "undefined behavior") –

+0

Trình biên dịch cho các hệ thống nhúng thường cung cấp cho người dùng của họ kiểm soát về nơi đi những gì. Nó không chắc rằng chuỗi chữ sẽ đi vào ROM và bạn không thể làm bất cứ điều gì về nó. –

3

Turbo C được tối ưu hóa để biên soạn nhanh, do đó, nó không có bất kỳ tính năng nào có thể làm chậm nó xuống. Việc nhận biết các chuỗi trùng lặp sẽ chậm lại, ngay cả khi chỉ nhỏ.

+4

Tôi nghĩ rằng giải thích này là sai. Các giá trị mặc định của Turbo C chỉ đơn giản là ở đó để cho phép mã bị hỏng sửa đổi hằng số chuỗi hoạt động theo mặc định. –

5

Từ trang hướng dẫn gcc:

-fmerge-hằng

Cố gắng để kết hợp hằng giống hệt nhau (hằng chuỗi và hằng dấu chấm động) trên đơn vị biên dịch.

Tùy chọn này là mặc định để biên dịch được tối ưu hóa nếu trình biên dịch và trình liên kết hỗ trợ nó. Sử dụng -fno-merge-constants để ngăn chặn hành vi này.

Được bật ở các cấp -O, -O2, -O3, -Os.

Do đó, đầu ra.

10

Hãy quên đi những câu trả lời trong cùng một dòng như

"Đó là bởi vì Turbo C là SO TOTALLY OLD và họ không thể làm điều đó THEN, bởi vì nó phải được nhanh chóng, nhưng GCC là hoàn toàn MỚI và RAD và đó là lý do tại sao nó làm điều đó! ".

Cả hai trình biên dịch đều hỗ trợ các chuỗi ký tự hợp nhất làm tùy chọn. Tùy chọn GCC (-fmerge-constants) được bật ở mức tối ưu, trong khi tùy chọn Turbo C (-d) được tắt theo mặc định. Nếu bạn đang sử dụng IDE TCC, hãy truy cập Options|Compiler...|Code Generation.. và kiểm tra "Duplicate strings merged".

+1

Tôi thấy câu trả lời của bạn khó đọc và ban đầu hoàn toàn hiểu nhầm nó, bởi vì báo giá không được nhận ra rõ ràng như vậy. Tôi hy vọng bạn có thể thay đổi định dạng của mình. Ngoài ra, thông tin tốt và hữu ích cho bất kỳ ai vẫn đang xử lý với TC, vì vậy: +1. –

+0

Ồ, tốt hơn nhiều. Cảm ơn bạn! –

0

Chú thích lịch sử: Vì địa chỉ nhỏ hơn hằng số số dấu phẩy động, FORTRAN được sử dụng để xử lý các hằng số dấu phẩy giống như C xử lý chuỗi. Kể từ khi bộ nhớ là quý giá, hằng số giống nhau sẽ được phân bổ cùng một không gian. Ngoài ra, việc truyền tham số luôn được thực hiện bằng tham chiếu. Điều này có nghĩa rằng nếu người ta chuyển một hằng số sang một thủ tục đã sửa đổi đối số của nó, các lần xuất hiện khác của "hằng số" đó sẽ thay đổi giá trị.

Do đó câu nói cũ: "Biến sẽ không; hằng số không."

Ngẫu nhiên, có ai nhận thấy lỗi trong bản in Turbo C 2.0 sẽ thất bại khi sử dụng định dạng như "% 1.1f" để in các số như 99,99 (kết quả đầu ra 00,0) không? Cố định trong 2,01, nó nhắc tôi về lỗi máy tính Windows 3.1.

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