Tôi đã được hỏi một câu hỏi phỏng vấn để thay đổi điểm vào của chương trình C hoặc C++ từ main()
thành bất kỳ chức năng nào khác. Làm thế nào là nó có thể?trong C++ chức năng chính là điểm vào chương trình làm thế nào tôi có thể thay đổi nó sang một chức năng khác?
Trả lời
Trong tiêu chuẩn C (và, tôi tin rằng, C++), bạn không thể, ít nhất là không cho một môi trường lưu trữ (nhưng xem bên dưới). Tiêu chuẩn quy định rằng điểm bắt đầu cho mã C là main
. Tiêu chuẩn (c99) không để lại nhiều phạm vi cho đối số:
5.1.2.2.1 Khởi động chương trình: (1) Chức năng được gọi lúc khởi động chương trình được đặt tên chính.
Vậy đó. Sau đó nó quế một chút về các thông số và giá trị trả về nhưng thực sự không có thay đổi gì về việc thay đổi tên.
Đó là dành cho môi trường được lưu trữ. Tiêu chuẩn này cũng cho phép một môi trường tự do (tức là, không có hệ điều hành nào, cho những thứ như hệ thống nhúng). Đối với môi trường tự do:
Trong môi trường tự do (trong đó thực thi chương trình C có thể diễn ra mà không có bất kỳ lợi ích nào của hệ điều hành), tên và loại chức năng được gọi là khởi động chương trình. Bất kỳ cơ sở thư viện nào có sẵn cho một chương trình tự do, trừ tập hợp tối thiểu theo yêu cầu của khoản 4, được xác định thực hiện.
Bạn có thể sử dụng "thủ đoạn gian trá" trong C triển khai để bạn có thể làm cho nó trông giống như main
không phải là điểm mấu chốt. Điều này thực tế là những gì mà những người tuân thủ Windows sớm đã làm để đánh dấu WinMain
là điểm bắt đầu.
cách đầu tiên: một mối liên kết có thể bao gồm một số mã khởi động trước chính trong một tập tin như start.o
và nó là đoạn mã này mà chạy để thiết lập môi trường C sau đó gọi main
. Không có gì để ngăn bạn thay thế bằng cái gì đó gọi số bob
.
Cách thứ hai: một số trình liên kết cung cấp tùy chọn đó với công tắc dòng lệnh để bạn có thể thay đổi mà không cần biên dịch lại mã khởi động.
Cách thứ ba: bạn có thể liên kết với đoạn mã này:
int main (int c, char *v[]) { return bob (c, v); }
và sau đó điểm vào của bạn cho đang của bạn là dường như bob
hơn main
.
Tuy nhiên, tất cả điều này, trong khi quan tâm có thể học tập, không làm thay đổi thực tế là tôi không thể nghĩ ra một tình huống đơn độc duy nhất trong nhiều thập kỷ của tôi về cắt mã, nơi đây sẽ là một trong hai cần thiết hoặc mong muốn.
Tôi sẽ hỏi người phỏng vấn: tại sao bạn muốn để thực hiện việc này?
như được gắn thẻ nó là một câu hỏi trong cuộc phỏng vấn của tôi bây giờ không phải là nó có thể hay không nếu có thể thì làm thế nào thanx cho ans. – Badr
+1 để tạo 'main' chỉ cần gọi một thứ khác. Đó là phương pháp đơn giản nhất và đa nền tảng để thực hiện điều này. – Seth
Không phải là có thể thực hiện một số hackery được xác định thực hiện với các nhà xây dựng của các đối tượng toàn cầu? Những con quỷ bay ra khỏi mũi của bạn trên các nền tảng khác được đảm bảo, tất nhiên. – slartibartfast
Nếu bạn đang ở trên VS2010, this có thể cung cấp cho bạn một số ý tưởng
Vì nó là dễ hiểu, điều này là không bắt buộc của chuẩn C++ và rơi trong lĩnh vực 'hành vi cụ thể triển khai thực'.
Sửa đổi đối tượng crt thực sự gọi hàm main()
hoặc cung cấp chức năng của riêng bạn (đừng quên tắt liên kết của bình thường).
Tôi có thể làm như thế nào? –
Từ tài liệu tiêu chuẩn C++ 3.6.1 Chức năng chính,
Một chương trình phải có một chức năng toàn cầu gọi là chính, mà là sự bắt đầu chỉ định của chương trình. Nó được thực hiện theo quy định cho dù một chương trình trong môi trường tự do là bắt buộc để xác định một chức năng chính.
Vì vậy, nó không phụ thuộc trên trình biên dịch của bạn/mối liên kết ...
Điều đó thật thú vị. Không có dấu hiệu nào trong cpp0x rằng câu đầu tiên chỉ áp dụng để lưu trữ, và 'sẽ' thường là một từ tiêu chuẩn có nghĩa là nó _must_ là như vậy. Vì vậy, nó xuất hiện rằng 'chính' phải tồn tại ngay cả đối với freestanding. Có thể một người nào đó với nhiều C++ - Standard-fu hơn tôi con số đó ra? Bạn có thể _have_ một 'main' mà không cần phải xác định nó? – paxdiablo
Thực ra dường như cũng giống như trường hợp của C. Tôi đang xem phần được lưu trữ. Phần freestanding là một chút lỏng lẻo với các yêu cầu. +1. – paxdiablo
@paxdiablo: Tôi nghĩ ý định là câu thứ hai đủ điều kiện cho câu đầu tiên, để nó có nghĩa là "Một chương trình [trong môi trường được lưu trữ] sẽ chứa ..." Tôi nghĩ "sẽ chứa" có nghĩa là "sẽ chứa [một định nghĩa của]; " Tôi không biết từ "chứa" có thể được hiểu như thế nào. –
Trên cửa sổ có một (chứ không phải không chính thống) cách để thay đổi điểm nhập cảnh của một chương trình: TLS
. Xem phần này để được giải thích thêm: http://isc.sans.edu/diary.html?storyid=6655
Đối với hệ thống dựa trên Solaris Tôi đã tìm thấy this. Bạn có thể sử dụng phần .init
cho mỗi nền tảng Tôi đoán:
pragma init (function [, function]...)
Nguồn:
pragma Điều này làm cho mỗi chức năng được liệt kê được gọi là trong quá trình khởi (trước chính) hoặc trong quá trình chia sẻ mô-đun tải, bằng cách thêm một cuộc gọi đến phần .init.
Các điểm nhập cảnh thực sự là _start
chức năng (thực hiện trong crt1.o).
Chức năng _start
chuẩn bị các đối số dòng lệnh và sau đó gọi main(int,char*[])
, bạn có thể thay đổi các điểm nhập cảnh từ _start
để mystart
bằng cách thiết lập một tham số mối liên kết:
g++ file.o -Wl,-emystart -o runme
Tất nhiên, đây là một sự thay thế cho điểm nhập _start
để bạn không nhận được các đối số dòng lệnh:
void mystart(){
}
Có, Chúng ta có thể thay đổi tên hàm chính thành bất kỳ tên nào khác cho ví dụ. Bắt đầu, bob, rem, v.v.
Trình biên dịch biết rằng nó phải tìm kiếm hàm main() trong toàn bộ mã?
Không có gì là tự động trong lập trình. ai đó đã thực hiện một số công việc để làm cho nó trông tự động cho chúng tôi.
do đó nó đã được xác định trong tệp khởi động mà trình biên dịch nên tìm kiếm chính().
chúng tôi có thể thay đổi tên chính thành bất kỳ điều gì khác, ví dụ: Bob và sau đó trình biên dịch sẽ chỉ tìm kiếm Bob().
Nó rất đơn giản:
Như bạn nên biết khi bạn sử dụng các hằng số trong c, trình biên dịch thực hiện một loại 'vĩ mô' thay đổi tên của hằng số cho giá trị tương ứng.
chỉ bao gồm một cuộc tranh luận #define
vào đầu mã của bạn với tên của chức năng khởi động tiếp theo là tên main
:
Ví dụ:
#define my_start-up_function (main)
Với gcc, khai báo hàm với thuộc tính ((constructor)) và gcc sẽ thực thi hàm này trước bất kỳ mã nào khác bao gồm cả main.
Đây là tính đầu cơ cao, nhưng bạn có thể có một initializer tĩnh thay vì chính:
bao gồm
int mymain()
{
std::cout << "mymain";
exit(0);
}
static int sRetVal = mymain();
int main()
{
std::cout << "never get here";
}
Bạn thậm chí có thể làm cho nó 'Java như', bằng cách đặt những thứ trong một constructor :
#include <iostream>
class MyApplication
{
public:
MyApplication()
{
std::cout << "mymain";
exit(0);
}
};
static MyApplication sMyApplication;
int main()
{
std::cout << "never get here";
}
Hiện tại. Người phỏng vấn có thể đã nghĩ về điều này, nhưng cá nhân tôi không bao giờ sử dụng chúng. Lý do là:
- Nó không thông thường. Mọi người sẽ không hiểu nó, nó không cần thiết để tìm điểm vào.
- Thứ tự khởi tạo tĩnh là không xác định. Đặt trong một biến tĩnh và bạn sẽ không bao giờ ngay bây giờ nếu nó được khởi tạo.
Điều đó nói rằng, tôi đã thấy nó được sử dụng trong sản xuất thay vì init()
cho người khởi tạo thư viện. Các caveat là, trên cửa sổ, (từ kinh nghiệm) statics của bạn trong một DLL có thể hoặc có thể không được khởi tạo dựa trên cách sử dụng.
Tôi nghĩ rằng việc xóa biểu tượng chính() không mong muốn khỏi đối tượng trước khi liên kết là dễ dàng.
Rất tiếc, tùy chọn điểm nhập cho g ++ không hoạt động đối với tôi (lỗi nhị phân trước khi nhập điểm nhập). Vì vậy, tôi dải không mong muốn entry-point từ tập tin đối tượng.
Giả sử chúng tôi có hai nguồn chứa chức năng điểm nhập.
- target.c chứa chính() chúng tôi không muốn.
- our_code.c chứa testmain() chúng tôi muốn là điểm vào.
Sau khi biên dịch (tùy chọn g ++ -c), chúng tôi có thể nhận được các tệp đối tượng sau.
- nhắm mục tiêu.o, có chứa chính() chúng tôi không muốn.
- our_code.o chứa testmain() chúng tôi muốn là điểm vào.
Vì vậy, chúng tôi có thể sử dụng objcopy để loại bỏ hàm main() không mong muốn.
objcopy --strip-biểu tượng = target.o chính
Chúng ta có thể xác định lại testmain() để main() sử dụng objcopy quá.
objcopy --redefine-sym testmain = our_code.o chính
Và sau đó chúng ta có thể liên kết cả hai trong số họ vào nhị phân.
g ++ target.o our_code.o -o our_binary.bin
này làm việc cho tôi. Bây giờ khi chúng tôi chạy our_binary.bin
điểm vào là our_code.c:main()
chức năng.
- 1. Tôi có thể đưa chức năng vào bên trong một chức năng khác không?
- 2. chức năng thoát trong chính
- 3. Chức năng ngủ trong chương trình android
- 4. Làm cách nào để chuyển 'dòng đối số' của một chức năng PowerShell sang một chức năng khác?
- 5. Chuyển trực tiếp sang chức năng C++ khác
- 6. javascript: Re-gán một chức năng với chức năng khác
- 7. Matlab - Kiểm tra xem chức năng xử lý là một chức năng hoặc chức năng cụ thể
- 8. chức năng chính Python
- 9. Chức năng eval thay thế là gì?
- 10. Tôi có thể chuyển mẫu vào một chức năng không?
- 11. Chức năng nào trong glibc gọi hàm chính là
- 12. Tôi có thể bắt đầu với chương trình chức năng bằng cách nào?
- 13. Gọi C chức năng/chương trình con trong mã Fortran
- 14. F # chức năng có thể thay đổi đối số
- 15. khai C chức năng trong một chức năng
- 16. AngularJS: Từ một nhà máy, làm cách nào tôi có thể gọi một chức năng khác
- 17. Có thể thay đổi chức năng repr trong python không?
- 18. Thay thế chức năng không thay thế
- 19. Chuyển đổi chức năng sang khối Simulink
- 20. Trong PHP là nó có thể sử dụng một chức năng bên trong một biến
- 21. Lập trình chức năng trong C/C++?
- 22. Chức năng trong một TSQL Chức năng
- 23. Gọi một số chức năng trước khi chính trong C
- 24. Chức năng nào áp dụng đối số của chính nó?
- 25. Tránh điểm chính (điểm vào) trong chương trình C
- 26. Một chức năng của dòng trong C?
- 27. Vĩnh viễn thay thế một chức năng
- 28. Có nên đi theo chức năng của thành viên hoặc chức năng bạn bè khi chức năng được cho là thay đổi trạng thái của đối tượng không?
- 29. Làm thế nào tôi có thể kiểm tra mã bytecode JVM cho một chức năng clojure?
- 30. chức năng phải ngắn như thế nào?
Bạn không. Nó phải là 'main', hoặc một số điểm vào được xác định. Không có cách tiêu chuẩn. – GManNickG
Phụ thuộc vào trình biên dịch/trình liên kết của bạn. – casablanca
Điểm vào của chương trình là nơi nó bắt đầu thực hiện ở cấp mã máy. Đó là hiếm khi nếu bao giờ 'chính'; thay vào đó, hàm điểm vào thực hiện một vài nhiệm vụ khởi tạo và sau đó, đối với một chương trình C hoặc C++, hãy gọi 'main'. Vì vậy, câu hỏi không có ý nghĩa. Bạn có chắc đó là câu hỏi chính xác không? –