週報日常 易錯題

2021-10-10 14:47:25 字數 4544 閱讀 4861

1.結構體內存對齊:

#include

struct aaa;

intmain()

程式輸出為:

441

824

其中32位作業系統:

char : 1 int :4 short : 2 unsigned int : 4 long : 4 unsigned long : 4 long long : 8 float : 4 double : 8 指標 : 4

64位作業系統

char : 1 int :4 short : 2 unsigned int : 4 long : 8 unsigned long : 8 long long : 8 float : 4 double : 8 指標 : 8

記憶體對齊:

每個引數按其型別的對齊引數(通常是這個型別的大小)和指定對齊引數(這裡預設是8位元組)中較小的乙個對齊。並且結構的長度必須為所用過的所有對齊引數的整數倍。不夠就補空位元組。

記憶體對齊主要遵循下面三個原則:

1.結構體變數的起始位址能夠被其位元組最長的引數大小整除

2.結構體每個引數相對於起始位址的偏移能夠被其自身大小整除,如果不能則在前乙個引數後面補充位元組

3.結構體總體大小能夠被最寬的成員的大小整除,如不能則在後面補充位元組

4. 如果巢狀了結構體的情況,被巢狀的結構體對齊到其自身對齊數的整數倍處(結構體的對齊數就是其內部成員中最大的對齊數),此時結構體的整體大小就是所有最大對齊數(含被巢狀結構體的對齊數)的整數倍。

第乙個是int 型四個位元組,佔0x0000-0x0003,第二個int型佔0x0004-0x0007,第三個char型佔0x0008-0x0009第四個double型8位元組,為滿足原則2,應佔0x0017-0x0024,所以char補齊7個位元組。且24%8==0滿足原則三,

即int(4)+int(4)+char(1)+補齊(7)+double(8)=24

當b和d換位結果相同。

再來乙個例子

struct s1

s;struct s2

;

struct s1長度char(1)+short(2)+補齊(1)+int(4)=8

struct s2長度char(1)補齊(3)+struct(8)+補齊(4)+double(8)=24

2.標頭檔案的使用和指標使用字串

#include

intmain()

改為:

#include

#include

intmain()

3.函式的宣告和引數存在的範圍

如下程式

int

main()

char*f

()

在使用函式應先在main函式前進行宣告,定義它的型別。

在函式使用中不能返回函式內部定義的值,如要使用需加入static全域性變數。

4.函式的呼叫

void

sum(

int a,

int b)

intmain()

在使用函式時不用void。

5.指標不可修改

char

* s=

"hello,xiyounet!"

;printf

("%s"

,s);s[0

]='h';

printf

("%s"

,s);

可修改為

#include

intmain()

輸出為:hello,xiyounet!hello,xiyounet!

6.main函式的引數是什麼?如何給main函式傳遞引數?**

(1)通過命令引數傳遞引數;

習慣上這兩個引數寫為argc(argument count)和ar**(argument vector)

argc是個整形變數,命令列引數個數,

char *ar**是字元指標陣列,

ar**[0] 為程式執行的全路徑名

ar**[1] 為在dos命令列中執行程式名後的第乙個字串;

ar**[2] 為執行程式名後的第二個字串;

argc:argc是執行程式時的命令列引數個數。需要注意的是,程式本身的檔案也算乙個。例如你在命令引數裡寫了2個引數,那argc等於3。

ar**:存的是命令列引數(字串)的首位址,包括程式本身的檔案和尾部的dull。

在專案——》屬性——》配置屬性——》除錯——》命令引數,設定命令引數就可以傳入引數

int

main

(int argc,

char

*ar**,

char

*envp)

return0;

}

輸出值即為你設定的引數。

envp裡存放正是系統的環境變數,可以右鍵單擊計算機——》屬性——》高階系統設定——》環境變數,開啟環境變數設定視窗

#include

#include

intmain

(int argc,

char

* ar**,

char

* envp)

system

("pause");

return0;

}

7.c和.cpp檔案是如何變成可執行檔案的?**

一.預編譯:

.處理源**檔案中的「#」開始的預編譯指令。如「#include」、「#define」等。具體如下:

巨集替換:將所有的「#define」刪除,並展開所有的巨集定義。 處理條件預編譯指令:如「#if" 「#endif」 「#elif」 "#else"指令:

處理「#include」預編譯指令,將被包含的標頭檔案插入到預編譯指令的位置。(遞迴插入,被包含的檔案還可能包含其他檔案)

刪除所有注釋(「//」、「/* */」)。 新增行號和檔案標識(以便編譯時期,出錯顯示行號、除錯使用行號資訊)

保留所有#pragma編譯器指令。

二.編譯:

詞法分析:源**經過掃瞄器,將源**的字串行分割成一系列的記號(關鍵字、識別符號、字面量(數字、字串)、特殊符號(如「+」「-」)),同時將識別符號存放到符號表,數字、字串常量放到文字表等工作,以備後續使用。

語法分析:語法分析器對掃瞄器產生的記號進行語法分析,生成語法樹(以表示式為節點的樹,檢驗表示式的邏輯性)。

語義分析:對靜態語義(編譯期可以確定的語義,包括宣告、型別匹配、型別轉換等)進行分析。如浮點型表示式賦給整型表示式時,型別不匹配,語義分析隱含執行了浮點型到整型轉換的過程。

**優化:源**級優化器(優化語法樹,如替換重複或簡單的表示式)進行優化。

unsigned int 的範圍為0~65535//32767+32768

unsigned char的範圍為0~255

9.左移運算子, 右移運算子,取反規則

printf

("%d",~

9);printf

("%d",(

-9)>>1)

;printf

("%d",(

-9)<<1)

;

-9二進位制為原碼10001001補碼為01110111

左移運算子左移補零,10010010,即為-18

右移運算子因為負數右移補一,10000101,即為-5

取反~1 = 0, ~0 = 1

~(01110111)=10001000即為8

10.&&和&

int i=0;

int j=0;

int ii = i++

&&++j;

printf

("%d %d %d\n"

, ii, i, j)

;i =0;

j =0

;ii =

++i & j++

;printf

("%d %d %d\n"

, ii, i, j)

;

輸出:

010011

原理:1.&&

只要左端條件式為假直接不成立,不會去判斷右端條件式。

相同點:只要有一端為假,則語句不成立,即ii = i++ && ++j;當i=0時不在執行j的命令所以j輸出為0。

2.&&左右兩端條件式有乙個為假就會不成立,但是兩端都會執行,比如 ii = ++i & j++;i=0即使為假,也會去判斷是否成立。即j自增。

另:strlen只計算\0之前的字元。

SQL測驗易錯題

sql 測驗 結果 17 20 您的回答 1.sql 指的是?您的回答 structured query language 2.哪個 sql 語句用於從資料庫中提取資料?您的回答 select 3.哪條 sql 語句用於更新資料庫中的資料?您的回答 update 4.哪條 sql 語句用於刪除資料庫...

c易錯題(一)

刷題也有幾天了,把自己刷題過程的錯題整理出來,以便以後不會再犯同樣的錯誤 1.已知int a 3 4 則下列可以表示a 1 2 元素的值的是 a.a 1 2 b.a 1 2 c.a 0 1 2 d.a 0 1 這道題看著不是很難,差不多可以選出a,但是卻不一定理解下邊的選項為啥錯。下邊我來乙個乙個分...

多型易錯題2

看下面 輸出結果。include include using namespace std class base class derive public base int main 請問輸出的i 是多少?base derive derive i 100 derive base 請按任意鍵繼續 由於在b...