1. C語言文件的編譯與執行的四個階段並分別描述
開發C程序有四個步驟:編輯、編譯、連接和運行。
任何一個體系結構處理器上都可以使用C語言程序,只要該體系結構處理器有相應的C語言編譯器和庫,那麼C源代碼就可以編譯並連接到目標二進制文件上運行。
1、預處理:導入源程序並保存(C文件)。
2、編譯:將源程序轉換為目標文件(Obj文件)。
3、鏈接:將目標文件生成為可執行文件(EXE文件)。
4、運行:執行,獲取運行結果的EXE文件。
(1)類型轉換在編譯的哪個階段擴展閱讀:
將C語言代碼分為程序的幾個階段:
1、首先,源代碼文件測試。以及相關的頭文件,比如stdio。H、由預處理器CPP預處理為.I文件。預編譯的。文件不包含任何宏定義,因為所有宏都已展開,並且包含的文件已插入。我歸檔。
2、編譯過程是對預處理文件進行詞法分析、語法分析、語義分析和優化,生成相應的匯編代碼文件。這個過程往往是整個程序的核心部分,也是最復雜的部分之一。
3、匯編程序不直接輸出可執行文件,而是輸出目標文件。匯編程序可以調用LD來生成可以運行的可執行程序。也就是說,您需要鏈接大量的文件才能獲得「a.out」,即最終的可執行文件。
4、在鏈接過程中,需要重新調整其他目標文件中定義的函數調用指令,而其他目標文件中定義的變數也存在同樣的問題。
2. C++類型轉換規則、何時發生隱式類型轉換及強制類型轉換適用場合
C++做為強類型語言,要求編譯期的類型聲明與檢查,要求表達式中各操作數的類型(包括賦值操作的左值和右值,以及形參和實參)具有一致性,但同時也允許一定的靈活性,允許類型在一定程度上的兼容,也就是允許類型遵循一定規則下的隱式轉換和強制轉換。
The type of the operand(s) determine whether an expression is legal and, if the expression is legal, determines the meaning of the expression. However, in C++ some types are related to one another. When two types are related, we can use an object or value of one type where an operand of the related type is expected. Two types are related if there is a conversion between them.
表達式是否合法取決於操作數的類型,而且合法的表達式其含義也由其操作數類型決定。但是,在 C++ 中,某些類型之間存在相關的依賴關系。若兩種類型相關,則可在需要某種類型的操作數位置上,使用該類型的相關類型對象或值。如果兩個類型之間可以相互 轉換 ,則稱這兩個類型相關。
1.1 The Arithmetic Conversions 算術轉換
The language defines a set of conversions among the built-in types. Among these, the most common are the arithmetic conversions , which ensure that the two operands of a binary operator, such as an arithmetic or logical operator, are converted to a common type before the operator is evaluated. That common type is also the result type of the expression.
C++ 語言為內置類型提供了一組轉換規則,其中最常用的是 算術轉換 。算術轉換保證在執行操作之前,將二元操作符(如算術或邏輯操作符)的兩個操作數轉換為同一類型,並使表達式的值也具有相同的類型。
The rules define a hierarchy of type conversions in which operands are converted to the widest type in the expression. The conversion rules are defined so as to preserve the precision of the values involved in a multi-type expression. For example, if one operand is of type long double, then the other is converted to type long double regardless of what the second type is.
算術轉換規則定義了一個類型轉換層次,該層次規定了操作數應按什麼次序轉換為表達式中最寬的類型。在包含多種類型的表達式中,轉換規則要確保計算值的精度。例如,如果一個操作數的類型是 long double,則無論另一個操作數是什麼類型,都將被轉換為 long double。
The simplest kinds of conversion are integral promotions . Each of the integral types that are smaller than int char, signed char, unsigned char, short, and unsigned shortis promoted to int if all possible values of that type fit in an int. Otherwise, the value is promoted to unsigned int. When bool values are promoted to int, a false value promotes to zero and true to one.
最簡單的轉換為 整型提升 :對於所有比 int 小的整型,包括 char、signed char、unsigned char、short 和 unsigned short,如果該類型的所有可能的值都能包容在 int 內,它們就會被提升為 int 型,否則,它們將被提升為 unsigned int。如果將 bool 值提升為 int ,則 false 轉換為 0,而 true 則轉換為 1。
需要注意的,上述所謂的轉換只是運算時的類型轉換,存儲時還會轉換為其聲明時的類型。
1.2 Conversions between Signed and Unsigned Types 有符號與無符號類型之間的轉換
When an unsigned value is involved in an expression, the conversion rules are defined to preserve the value of the operands. Conversions involving unsigned operands depend on the relative sizes of the integral types on the machine. Hence, such conversions are inherently machine dependent.
若表達式中使用了無符號( unsigned )數值,所定義的轉換規則需保護操作數的精度。unsigned 操作數的轉換依賴於機器中整型的相對大小,因此,這類轉換本質上依賴於機器。
In expressions involving shorts and ints, values of type short are converted to int. Expressions involving unsigned short are converted to int if the int type is large enough to represent all the values of an unsigned short. Otherwise, both operands are converted to unsigned int. For example, if shorts are a half word and ints a word, then any unsigned value will fit inside an int. On such a machine, unsigned shorts are converted to int.
包含 short 和 int 類型的表達式, short 類型的值轉換為 int 。如果 int 型足夠表示所有 unsigned short 型的值,則將 unsigned short 轉換為 int,否則,將兩個操作數均轉換為 unsigned int 。例如,如果 short 用半字表示而 int 用一個字表示,則所有 unsigned 值都能包容在 int 內,在這種機器上, unsigned short 轉換為 int。
The same conversion happens among operands of type long and unsigned int. The unsigned int operand is converted to long if type long on the machine is large enough to represent all the values of the unsigned int. Otherwise, both operands are converted to unsigned long.
long 和 unsigned int 的轉換也是一樣的。只要機器上的 long 型足夠表示 unsigned int 型的所有值,就將 unsigned int 轉換為 long 型,否則,將兩個操作數均轉換為 unsigned long 。
On a 32-bit machine, long and int are typically represented in a word. On such machines, expressions involving unsigned ints and longs are converted to unsigned long.
在 32 位的機器上,long 和 int 型通常用一個字長表示,因此當表達式包含 unsigned int 和 long 兩種類型,其操作數都應轉換為 unsigned long 型。
Conversions for expressions involving signed and unsigned int can be surprising. In these expressions the signed value is converted to unsigned. For example, if we compare a plain int and an unsigned int, the int is first converted to unsigned. If the int happens to hold a negative value, the result will be converted as described as belows, with all the attendant problems discussed there.
對於包含 signed 和 unsigned int 型的表達式,其轉換可能出乎我們的意料。表達式中的 signed 型數值會被轉換為 unsigned 型。例如,比較 int 型和 unsigned int 型的簡單變數,系統首先將 int 型數值轉換為 unsigned int 型,如果 int 型的值恰好為負數,其結果將以下述方法轉換,並帶來其所有副作用。
The compiler applies conversions for both built-in and class type objects as necessary. Implicit type conversions take place in the following situations:
編譯器在必要時將類型轉換規則應用到內置類型和類類型的對象上。在下列情況下,將發生隱式類型轉換:
In expressions with operands of mixed types, the types are converted to a common type:
在混合類型的表達式中,其操作數被轉換為相同的類型:
An expression used as a condition is converted to bool:
用作條件的表達式被轉換為 bool 類型:
Conditions occur as the first operand of the conditional (?:) operator and as the operand(s) to the logical NOT (!), logical AND (&&), and logical OR (||) operators. Conditions also appear in the if, while, for, and do while statements.
條件操作符(?:)中的第一個操作數以及邏輯非(!)、邏輯與(&&)和邏輯或(||)的操作數都是條件表達式。出現在 if、while、for 和 do while 語句中的同樣也是條件表達式。
An expression used to initialize or assign to a variable is converted to the type of the variable:
用一表達式初始化某個變數,或將一表達式賦值給某個變數,則該表達式被轉換為該變數的類型:
In addition,implicit conversions also occur ring function calls.
另外,在函數調用中也可能發生隱式類型轉換。
3.1 static_cast
Any type conversion that the compiler performs implicitly can be explicitly requested by using a static_cast:
編譯器隱式執行的任何類型轉換都可以由 static_cast 顯式完成:
Such casts are useful when assigning a larger arithmetic type to a smaller type. The cast informs both the reader of the program and the compiler that we are aware of and are not concerned about the potential loss of precision. Compilers often generate a warning for assignments of a larger arithmetic type to a smaller type. When we provide the explicit cast, the warning message is turned off.
當需要將一個較大的算術類型賦值給較小的類型時,使用強制轉換非常有用。此時,強制類型轉換告訴程序的讀者和編譯器:我們知道並且不關心潛在的精度損失。對於從一個較大的算術類型到一個較小類型的賦值,編譯器通常會產生警告。當我們顯式地提供強制類型轉換時,警告信息就會被關閉。
A static_cast is also useful to perform a conversion that the compiler will not generate automatically. For example, we can use a static_cast to retrieve a pointer value that was stored in a void* pointer:
如果編譯器不提供自動轉換,使用 static_cast 來執行類型轉換也是很有用的。例如,下面的程序使用 static_cast 找回存放在 void* 指針中的值:
When we store a pointer in a void* and then use a static_cast to cast the pointer back to its original type, we are guaranteed that the pointer value is preserved. That is, the result of the cast will be equal to the original address value.
可通過 static_cast 將存放在 void* 中的指針值強制轉換為原來的指針類型,此時我們應確保保持指針值。也就是說,強制轉換的結果應與原來的地址值相等。
3.2 const_cast
A const_cast, as its name implies, casts away the constness of its expression. For example, we might have a function named string_ that we are certain reads, but does not write, its single parameter of type char*. If we have access to the code, the best alternative would be to correct it to take a const char*. If that is not possible, we could call string_ on a const value using a const_cast:
const_cast ,顧名思義,將 轉換掉 表達式的 const 性質。例如,假設有函數 string_,只有唯一的參數,為 char* 類型,我們對該函數只讀不寫。在訪問該函數時,最好的選擇是修改它讓它接受 const char* 類型的參數。如果不行,可通過 const_cast 用一個 const 值調用 string_ 函數:
Only a const_cast can be used to cast away constness. Using any of the other three forms of cast in this case would result in a compile-time error. Similarly, it is a compile-time error to use the const_cast notation to perform any type conversion other than adding or removing const.
只有使用 const_cast 才能將 const 性質轉換掉。在這種情況下,試圖使用其他三種形式的強制轉換都會導致編譯時的錯誤。類似地,除了添加或刪除 const 特性,用 const_cast 符來執行其他任何類型轉換,都會引起編譯錯誤。
3.3 reinterpret_cast
A reinterpret_cast generally performs a low-level reinterpretation of the bit pattern of its operands.
reinterpret_cast 通常為操作數的位模式提供較低層次的重新解釋。
A reinterpret_cast is inherently machine-dependent. Safely using reinterpret_cast requires completely understanding the types involved as well as the details of how the compiler implements the cast.
reinterpret_cast 本質上依賴於機器。為了安全地使用 reinterpret_cast,要求程序員完全理解所涉及的數據類型,以及編譯器實現強制類型轉換的細節。
在引入命名的強制類型轉換操作符之前,顯式強制轉換用圓括弧將類型括起來實現:
The effect of this cast is the same as using the reinterpret_cast notation. However, the visibility of this cast is considerably less, making it even more difficult to track down the rogue cast.
效果與使用 reinterpret_cast 符號相同,但這種強制轉換的可視性比較差,難以跟蹤錯誤的轉換。
Depending on the types involved, an old-style cast has the same behavior as a const_cast, a static_cast, ora reinterpret_cast. When used where a static_cast or a const_cast would be legal, an old-style cast does the same conversion as the respective named cast. If neither is legal, then an old-style cast performs a reinterpret_cast. For example, we might rewrite the casts from the previous section less clearly using old-style notation:
舊式強制轉換依賴於所涉及的數據類型,具有與 const_cast、 static_cast 和 reinterpret_cast 一樣的行為。在合法使用 static_cast 或 const_cast 的地方,舊式強制轉換提供了與各自對應的命名強制轉換一樣的功能。如果這兩種強制轉換均不合法,則舊式強制轉換執行 reinterpret_cast 功能。例如,我們可用舊式符號重寫上一節的強制轉換:
By using a cast, the programmer turns off or dampens normal type-checking. We strongly recommend that programmers avoid casts and believe that most well-formed C++ programs can be written without relying on casts.
強制類型轉換關閉或掛起了正常的類型檢查。強烈建議程序員避免使用強制類型轉換,不依賴強制類型轉換也能寫出很好的 C++ 程序。
arithmetic conversion(算術轉換)
A conversion from one arithmetic type to another. In the context of the binary arithmetic operators, arithmetic conversions usually attempt to preserve precision by converting a smaller type to a larger type (e.g., small integral types, such as char and short, are converted to int).
算術類型之間的轉換。在使用二元算術操作符的地方,算術轉換通常將較小的類型轉換為較大的類型,以確保精度(例如,將小的整型 char 型和 short 型轉換為 int 型)。
dynamic_cast
Used in combination with inheritance and run-time type identification.
用於結合繼承和運行時類型識別。
implicit conversion(隱式類型轉換)
A conversion that is automatically generated by the compiler. Given an expression that needs a particular type but has an operand of a differing type , the compiler will automatically convert the operand to the desired type if an appropriate conversion exists.
編譯器自動實現的類型轉換。假設表達式需要某種特定類型的數值,但其操作數卻是其他不同的類型, 此時如果系統定義了適當的類型轉換 ,編譯器會自動根據轉換規則將該操作數轉換為需要的類型。
integral promotions(整型提升)
Subset of the standard conversions that take a smaller integral type to its most closely related larger type. Integral types (e.g. short, char, etc.) are promoted to int or unsigned int.
整型提升是標准類型轉換規則的子集,它將較小的整型轉換為最接近的較大數據類型。整型(如 short、char 等)被提升為 int 型或 unsigned int 型。
reinterpret_cast
Interprets the contents of the operand as a different type. Inherently machine-dependent and dangerous.
將操作數內容解釋為另一種不同的類型。這類強制轉換本質上依賴於機器,而且是非常危險的。
static_cast
An explicit request for a type conversion that the compiler would do implicitly. Often used to override an implicit conversion that the compiler would otherwise perform.
編譯器隱式執行的任何類型轉換都可以由 static_cast 顯式完成。我們常常使用 static_cast 取代由編譯器實現的隱式轉換。
-End-
3. 傳統意義上的c/c++語言,類型推斷是在哪個階段完成的
不存在類型推斷,根據聲明,c/c++編譯器可以直接獲取該變數類型。如果是類型檢查的話在詞法分析階段就可以捕獲類型不匹配錯誤。當然如果非要放到語法分析階段也可以。
4. C語言源程序的編譯過程包括哪三個階段
編譯:將源程序轉換為擴展名為.obj的二進制代碼
連接:將obj文件進行連接,加入庫函數等生成可執行文件
運行:執行可執行文件,有錯返回修改,無錯結束
5. 編譯器的工作分為哪幾個階段
編譯器就是一個普通程序,沒什麼大不了的
什麼是編譯器?
編譯器是一個將高級語言翻譯為低級語言的程序。
首先我們一定要意識到編譯器就是一個普通程序,沒什麼大不了的。
在沒有弄明白編譯器如何工作之前你可以簡單的把編譯器當做一個黑盒子,其作用就是輸入一個文本文件輸出一個二進制文件。
基本上編譯器經過了以下幾個階段,等等,這句話教科書上也有,但是我相信很多同學其實並沒有真正理解這幾個步驟到底在說些什麼,為了讓你徹底理解這幾個步驟,我們用一個簡單的例子來講解。
假定我們有一段程序:
while (y < z) {
int x = a + b;
y += x;
}
那麼編譯器是怎樣把這一段程序人類認識的程序轉換為CPU認識的二進制機器指令呢?
提取出每一個單詞:詞法分析
首先編譯器要把源代碼中的每個「單詞」提取出來,在編譯技術中「單詞」被稱為token。其實不只是每個單詞被稱為一個token,除去單詞之外的比如左括弧、右括弧、賦值操作符等都被稱為token。
從源代碼中提取出token的過程就被稱為詞法分析,Lexical Analysis。
經過一遍詞法分析,編譯器得到了以下token:
T_While while
T_LeftParen (
T_Identifier y
T_Less <
T_Identifier z
T_RightParen )
T_OpenBrace {
T_Int int
T_Identifier x
T_Assign =
T_Identifier a
T_Plus +
T_Identifier b
T_Semicolon ;
T_Identifier y
T_PlusAssign +=
T_Identifier x
T_Semicolon ;
T_CloseBrace }
就這樣一個磁碟中保存的字元串源代碼文件就轉換為了一個個的token。
這些token想表達什麼意思:語法分析
有了這些token之後編譯器就可以根據語言定義的語法恢復其原本的結構,怎麼恢復呢?
原來,編譯器在掃描出各個token後根據規則將其用樹的形式表示出來,這顆樹就被稱為語法樹。
語法樹是不是合理的:語義分析
有了語法樹後我們還要檢查這棵樹是不是合法的,比如我們不能把一個整數和一個字元串相加、比較符左右兩邊的數據類型要相同,等等。
這一步通過後就證明了程序合法,不會有編譯錯誤。
6. C語言強制類型轉換
強制類型轉換是把變數從一種類型轉換為另一種數據類型。
例如,如果您想存儲一個 long 類型的值到一個簡單的整型中,您需要把 long 類型強制轉換為 int 類型。您可以使用強制類型轉換運算符來把值顯式地從一種類型轉換為另一種類型。
(6)類型轉換在編譯的哪個階段擴展閱讀:
舉例說明
使用強制類型轉換運算符把一個整數變數除以另一個整數變數,得到一個浮點數:
#include <stdio.h>int main()
{
int sum = 17, count = 5;
double mean;
mean = (double) sum / count;
printf("Value of mean : %f
", mean );
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Value of mean : 3.400000
7. C語言的編譯階段指的什麼階段
把你寫的程序代碼翻譯為機器可以讀懂的語言,也就是機器語言。
也就是把程序代碼翻譯為001010101的二進製程序代碼
8. 何謂隱式類型轉換其轉換規則如何
數值的類型轉換分為強制性轉換(我們人為的轉換)和自動轉換(也就是隱式轉換,編譯器自己進行的轉換,不經我們的同意)
要想知道什麼是隱式轉換,那你首先得清楚數值共可以分為幾個類型,其中包括char=short<int<unsingned<long=float<double.他們的精確度是隨之增加的,他們能表示數值的范圍也是越來越大的。如果同類型的數值相操作(加減乘除等),是不會發生類型轉換,如果是不同類型數值相操作,比如說short型數值和int型數值相操作,那麼小取值范圍的類型(short)會先隱式轉換為取值范圍大的類型(int),然後再進行數值間的操作,得出來的結果也是int型。
我說道這里不知道你能否看懂。建議你看看譚浩強的《c程序設計》,裡面講的比較詳細。
9. java代碼的編譯期綁定和運行期綁定是什麼意思
如果打包成jar的話很好如果是exe的話就有點麻煩了可參考:想要把java生成可執行文件需要第三方軟體的支持,不過在沒有安裝JDK的機器上是不可能運行JAVA程序的,哪怕是編譯成為exe文件。將Java應用程序本地編譯為EXE的幾種方法(推薦使用JOVE和JET)1.從獲得一個TowerJ編譯器,該編譯器可以將你的CLASS文件編譯成EXE文件。2.利用微軟的SDK-Java4.0所提供的jexegen.exe創建EXE文件,這個軟體可以從微軟的網站免費下載,地址如下:7.Instantiations公司的JOVE/jove/ejovesystem.htmJOVE公司合並了以前的SuperCede,一個優秀的本地編譯器,現在SuperCede已經不復存在了。8.JToEXEBravoZuluConsulting,Inc開發的一款本地編譯器,本來可以從該公司的網頁上免費下載的,不過目前在該公司的主頁上找不到了。