c語言基礎學習03_數據類型與運算符

============================================================================= 涉及到的知識點有:編碼風格、c語言的數據類型、常量、計算機裏面的進制、原碼反碼補碼、int類型、整數的溢出、大端對齊與小端對齊、char類型(字符類型)、 浮點類型float \ double \ long double、類型限定、字符串格式化輸出與輸入、基本運算符、運算符的優先級、類型轉換等。

============================================================================= gcc -o a1.s -S a1.c gcc把c語言代碼轉換爲彙編代碼 ----------------------------------------------------------------------------- 關於編碼風格的說明:

int dog_name;  linux編碼風格 int dog_age;

int iDogName;   微軟編碼風格 int iDogAge;

編碼一定要工整,這是初學者容易忽略的。

============================================================================= C語言的數據類型:

1、常量:在此程序運行中不可變化的量(注意常量也是有類型的哦!) 第一種定義常量的方法: #define MAX 100 這種定義常量的方法一般叫宏常量,所以有時也叫定義了一個宏,宏常量的常量名一般是大寫字母。 第二種定義常量的方法: const int max = 0; const常量,

一般區別:c語言裏面用宏常量比較多,c++用const比較多。 ----------------------------------------------------------------------------- "你好"    字符串常量 500       500本身是整數常量

比如: int a = 500; 500 = 0; //這句是錯誤的

============================================================================= 計算機裏面的進制: 十進制   二進制   八進制   十六進制 0      0           0             0 1      1           1        1 2      10              2                  2 3      11              3                  3 4      100            4                  4 5      101            5                  5 6      110            6                  6 7           111            7                  7 8           1000         10                 8 9           1001         11                 9 10         1010         12                 a 11         1011          13                 b 12         1100          14                 c 13         1101          15                 d 14         1110          16                 e 15         1111           17                 f 16         10000         20               10 17         10001         21               11 ----------------------------------------------------------------------------- 一個二進制的位就是一個bit(比特) 8個bit是一個BYTE(字節) 2個BYTE是一個WORD(字) 2個WORD是一個DWORD(雙字) 1024個BYTE 是1KBYTE 1024K 是1M 1024M 是1G 1024G 是1T 1024T 是1P 1024P 是1E 1024E 是1Z 1024Z 是1Y ----------------------------------------------------------------------------- 512GB     硬盤(單位是字節) 12Mb     網絡帶寬(單位是比特) 200MB   文件的大小(單位是字節) 100Mb      網卡(單位是比特) ----------------------------------------------------------------------------- 進制之間的轉換: 10101010111111010101011 把一個二進制數轉化爲10進制是很困難的,但是計算機使用的就是二進制。

從右到左起,每3個一組,不夠的補零。 010 101 010 111 111 010 101 011 轉化爲8進制 2      5    2      7     7    2     5    3

從右到左起,每4個一組,不夠的補零。 0101 0101 0111 1110 1010 1011 轉化爲16進制 5       5       7       e       a       b

二進制其實和8進制、16進制是一一對應的,在計算機語言中一般不直接用二進制,c語言更多的用8進制或者16進制 ----------------------------------------------------------------------------- 把十進制的56轉化爲2進制 先把這個數轉化爲8進制,然後把8進制直接對應爲2進制

用56除以8,分別取餘數和商數 8     56        7   0   0   7 70      轉化爲8進制的結果 111 000   轉化爲2進制的結果 ----------------------------------------------------------------------------- 16   100   6   4   0   6 64      轉化爲8進制的結果 0110 0100   轉化爲2進制的結果 ----------------------------------------------------------------------------- 2  100   50    0   25    0   12      1   6      0   3           0   1           1   0           1 1100100     直接轉化爲2進制的結果 ============================================================================= 這些數對於計算機來講,他們是怎麼放的呢??

1、原碼 例如:7的二進制是多少?(即7的二進制原碼如下) 111 0000 0111 用一個BYTE(字節)表示 0000 0000 0000 0111 用一個WORD(字)表示(即用2個字節來表示) 0000 0000 0000 0000 0000 0000 0000 0111 用一個DWORD(雙字)表示(即用4個字節來表示)

那麼 -7 該如何表示呢?原則是:最高位爲符號位,符號位0代表正數,1代表負數 -7的二進制是多少?(即 -7 的二進制原碼如下) 1000 0111 用一個BYTE(字節)表示 1000 0000 0000 0111 用一個WORD(字)表示(即用2個字節來表示) 1000 0000 0000 0000 0000 0000 0000 0111 用一個DWORD(雙字)表示(即用4個字節來表示) ----------------------------------------------------------------------------- 2、反碼:一個數若爲正值,則反碼和原碼相同;一個數若爲負值,則符號位爲1,其餘各位與原碼相反。 7的反碼 0000 0111 用一個BYTE(字節)表示 0000 0000 0000 0111 用一個WORD(字)表示(即用2個字節來表示) 0000 0000 0000 0000 0000 0000 0000 0111 用一個DWORD(雙字)表示(即用4個字節來表示)

-7的反碼 1111 1000 用一個BYTE(字節)表示 1111 1111 1111 1000 用一個WORD(字)表示(即用2個字節來表示) 1111 1111 1111 1111 1111 1111 1111 1000 用一個DWORD(雙字)表示(即用4個字節來表示) ----------------------------------------------------------------------------- 3、補碼:一個數若爲正值,則補碼和原碼相同;一個數若爲負值,則符號位爲1,其餘各位與原碼相反,最後對整個數 +1 。 7的補碼 0000 0111 用一個BYTE(字節)表示 0000 0000 0000 0111 用一個WORD(字)表示(即用2個字節來表示) 0000 0000 0000 0000 0000 0000 0000 0111 用一個DWORD(雙字)表示(即用4個字節來表示)

-7的補碼(在計算機內部,正數和負數都是以補碼的方式存放的。又因爲正數的補碼是其本身,所以簡言之:所有的負數都是以補碼的方式存放的。好處是:用補碼進行運算,得到補碼,減法可以通過加法來實現,也即不用考慮符號位了!!)

1111 1001 用一個BYTE(字節)表示 1111 1111 1111 1001 用一個WORD(字)表示(即用2個字節來表示) 1111 1111 1111 1111 1111 1111 1111 1001 用一個DWORD(雙字)表示(即用4個字節來表示) ----------------------------------------------------------------------------- 小例題: 知道補碼如何求原碼?答:符號位不變,先 -1 再取反即可;或者符號位不變,先取反,再 +1 也可以哦! 補碼 1111 1111 1111 1111 1111 1111 1111 0101 如果是負數,是負幾? 1000 0000 0000 0000 0000 0000 0000 1011 這個數是-11的補碼。

============================================================================= sizeof   關鍵字作用是:得到某一數據類型在內存中佔用的大小,單位是:字節 sizeof   不是函數,所以不需要包含任何頭文件 其實呢,sizeof返回值的類型是size_t,size_t類型在32位操作系統下是一個無符號的整數。

例如: int a = 0; int b = 0; b = sizeof(a);//得到a在內存中佔用的大小,單位是:字節

0000 0000 0000 0000 0000 0000 0000 0000  int a = 0; 0000 0000 0000 0000 0000 0000 0000 1010  int a = 10; 1111  1111 1111  1111  1111  1111 1111   0110  int a = -10; ----------------------------------------------------------------------------- 有符號數的最高位0代表正數,1代表負數;(即有正有負) 無符號數的最高位就是數的一部分,不是正負的意思(即無符號數只有正數)

例如: 有符號數的原碼 0000 0000 0 0000 1000 8 1000 1000 -8

無符號數的原碼 0000 0000 0 0000 1000 8 1000 1000 88(16進制的88) ----------------------------------------------------------------------------- 一個BYTE(字節)作爲有符號數,最小是多少-128,最大是多少127 -128 -127 ...... -1 0 1 2 ...... 127

一個BYTE(字節)無符號數,最小是0,最大是255 0 1 2 ...... 254 255 ----------------------------------------------------------------------------- 有符號數才區分原碼補碼,無符號數都是原碼

============================================================================= c語言從來不規定數據類型的大小,具體某種數據類型多大,和系統相關。 也即:在同一個系統下,具體的一種數據類型大小是相同的。 ----------------------------------------------------------------------------- 變量:就是在程序運行中可以更改值的量 int a;   //定義了一個變量 a = 0; a = 2; ----------------------------------------------------------------------------- 如果直接寫一個整數,默認是10進制的整數 20      表示10進制的20 020    表示8 進制的20 0x20     表示16進制的20 ----------------------------------------------------------------------------- %d 的意思是按照十進制的有符號整數輸出 %u 的意思是按照十進制的無符號整數輸出 %o 的意思是按照八進制的有符號整數輸出 %x 的意思是按照十六進制的有符號整數輸出(小寫) %X 的意思是按照十六進制的有符號整數輸出(大寫) ----------------------------------------------------------------------------- 例如:-11在內存中存放是以補碼的形式存放的。-11的補碼如下: 1111 1111 1111 1111 1111 1111 1111 0101 f   f     f     f       f       f        f      5 -11轉換成十進制就是:4294967285

============================================================================= signed int a;    //定義了一個有符號的int(關鍵字signed一般不用寫) unsigned int b;     //定義了一個無符號的int

long int 是長整型,在32位系統下是4個字節,在64位linux系統下是8個字節,在64位的windows系統下是4個字節。(大小是不穩定的) long long int 是長長整型,在32位系統和64位系統下都是8個字節。(大小是穩定的)

unsigned short int    無符號的短整數類型(大小爲2個BYTE(字節)) unsigned long int          無符號的長整數類型(大小是不穩定的) unsigned long long int  無符號的長長整數類型(大小是穩定的) ----------------------------------------------------------------------------- 100      直接這樣寫表示是一個有符號的int 100u    直接這樣寫表示是一個無符號的int 100l          直接這樣寫表示是一個有符號的long 100ul        直接這樣寫表示是一個無符號的long 100ll         直接這樣寫表示是一個有符號的long long 100ull       直接這樣寫表示是一個無符號的long long

注意:在c語言中表達一個整數的常量,如果什麼標示都不加,那麼默認類型是signed int(有符號的int)

============================================================================= 整數的溢出:當超過一個整型能夠存放最大的範圍時,整數會溢出。 有兩種溢出: 符號位溢出:該溢出會導致數的正負發生改變。 最高位溢出:該溢出會導致最高位的丟失。 ----------------------------------------------------------------------------- 1、符號位溢出例子:該溢出會導致數的正負發生改變。 例如:   int a = 0x7fffffff;   a = a + 3;   printf("%d\n",a);

int(默認爲有符號的int) 0111 1111 1111 1111 1111 1111 1111 1111 7       f     f       f       f        f       f       f +1得到: 1000 0000 0000 0000 0000 0000 0000 0000 +2得到: 1000 0000 0000 0000 0000 0000 0000 0001 +3得到:(+3後該數變爲負數了,而在計算機中,負數都是以補碼的方式存放的,即該負數就是補碼啦,那麼知道補碼求原碼) 1000 0000 0000 0000 0000 0000 0000 0010

因爲printf("%d\n",a);%d的意思是按照十進制的有符號整數輸出的,即輸出的是有符號的原碼, 所以知道補碼如何求原碼?答:符號位不變,先取反,再 +1 即得;或者 符號位不變,先 -1 再取反也可以哦! 求得原碼是: 1111 1111 1111 1111 1111 1111 1111 1110 7    f        f       f       f       f       f        e 則輸出的結果是:-2147483646 ----------------------------------------------------------------------------- 2、最高位溢出例子:該溢出會導致最高位的丟失。 例如: int 6 = 0xffffffff; b = b + 3; printf("%u\n",b); unsigned int(無符號的int) 1111 1111 1111 1111 1111 1111 1111 1111 1 0000 0000 0000 0000 0000 0000 0000 0000 1 0000 0000 0000 0000 0000 0000 0000 0001 1 0000 0000 0000 0000 0000 0000 0000 0010 因爲printf("%u\n",b);%u的意思是按照十進制的無符號整數輸出的,即輸出的是無符號的原碼, 原碼是: 0000 0000 0000 0000 0000 0000 0000 0010 (把高位1丟掉了) 則輸出的結果是:2

============================================================================= 大端對齊與小端對齊

計算機的內存最小單位是什麼?是BYTE,是字節。 一個大於BYTE的數據類型在內存中存放的時候要有先後順序。

高內存地址放整數的高位,低內存地址放整數的低位,這種方式叫倒着放,術語叫小端對齊。電腦X86和手機ARM都是小端對齊的。 高內存地址放整數的低位,低內存地址放整數的高位,這種方式叫正着放,術語叫大端對齊。很多Unix服務器的cpu都是大端對齊的。

如下圖例子:(有個圖片)

============================================================================= char類型(字符類型)

單引號引起來的字符就是char常量 'a'     是一個字符類型的常量a,'a'其實指的是字符a的ASCII碼,即所有的英文字符都是一個BYTE的整數,這個整數就是ASCII碼。 "a"      是一個字符串類型的常量 '2'         這個是字符型的2,而不是數字2 ----------------------------------------------------------------------------- char a;    //定義了一個字符類型的變量,名字叫a。 char a = 'a'; //等號左邊是一個變量,名字叫a;右邊是一個字符常量,就是字母a。 ----------------------------------------------------------------------------- 本質問題,至關重要: char的本質其實是一個整數,大小是一個BYTE(字節),在c語言中沒有BYTE這種數據類型,用char替代。 ----------------------------------------------------------------------------- 1 #include <stdio.h> 2 3 int main() 4 { 5      char a = 'a';       //等號左邊是一個變量,名字叫a;右邊是一個字符常量,就是字母a。 6      int i = sizeof(a); 7      printf("%d\n", i);     //輸出1 8      a = 4;           //此時char是一個有符號的char,也即有符號的int(只是該int的大小爲1個字節) 9      a = a + 5; 10    printf("%d\n", a);    //輸出9 11    a = 0x7f; 12    a += 3; 13    printf("%d\n", a);    //輸出-126 14    unsigned char b = 0xff; //此時char是一個無符號的char,也即無符號的int(只是該int的大小爲1個字節) 15    b = b +2; 16    printf("%u\n", b);    //輸出1 17    a = 'B';                   //把字符B的ASCII碼賦值給了a。 18    printf("%d\n", a);    //輸出66 19    a = 'b';                   //把字符b的ASCII碼賦值給了a。 20    printf("%d\n", a);   //輸出98 21    a = 99; 22    printf("%c\n", a);   //輸出c c% 輸出一個char類型的常量或者變量 23    return 0; 24 }

符號位溢出:該溢出會導致數的正負發生改變。 //此時char是一個有符號的char,也即有符號的int(只是該int的大小爲1個字節) 7  f 0111 1111 先加1得: 1000 0000 再加1得: 1000 0001 再加1得: 1000 0010 得到的就是負數了,而負數就是補碼,就是知補碼,求原碼? 求原碼得: 1111 1101 +1 得 1111 1110 輸出的是:-126

最高位溢出:該溢出會導致最高位的丟失。 //此時char是一個無符號的char,也即無符號的int(只是該int的大小爲1個字節) f  f 1111 1111 先加1得: 1 0000 0000 再加1得: 1 0000 0001 得到1;因爲一個char最大能放8個比特(bit),從左往右 ----------------------------------------------------------------------------- signed char        min:-128 ~ max:127 unsigned char    min: 0 ~ max:255 ----------------------------------------------------------------------------- 鍵盤的ASCII很多,有些ASCII沒法輸入,比如退格效果(Backspace)怎麼輸入呢?用轉義字符 \ 例如: char a = 'a';            //等號左邊是一個變量,名字叫a;右邊是一個字符常量,就是字母a。 printf("hello world"); a = '\b';           //'\b'表示一個退格的ASCII printf("%c",a);        //輸出結果爲:hello worl printf("%c%c",a,a);  //輸出結果爲:hello wor

不可打印的字符(char)如下: \a   警報 \b   退格 \n   換行 \r    回車 \t    製表符 \\    斜槓 \'    單引號 \"    雙引號 \?      問號 ============================================================================= 浮點類型:float、double、long double char、short、int、long、long long這些類型都是存放整型,但這些類型無法處理小數

浮點類型   Linux系統下大小     windows系統下大小 float      4個字節           4個字節 double       8個字節             8個字節 long double    16個字節                12個字節 long           8個字節                  4個字節

%f   %lf    用來輸出一個浮點數,不能用輸出整型的轉移符來輸出一個浮點數 ----------------------------------------------------------------------------- 小練習: 一個浮點數變量,小數點後面有一位 例如: 3.5 3.7 2.8 1.1 核心代碼: double a = 4.5 int b = a + 0.5; a = b; printf("%lf\n", a); //輸出的時候要四捨五入,例如4.5輸出5.000000

============================================================================= 類型限定: const       是定義一個常量,不可以被改變的 volatile     代表定義一個變量,這個變量可能在cpu指令之外被改變 volatile int a;      //定義了一個volatile類型的int變量,通過volatile定義的變量,編譯器不會自作聰明的去優化這個變量相關的代碼。 register int a;     //定義了一個變量,是寄存器變量。建議把一個變量放入cpu的寄存器可以提升程序的運行效率。            //register是建議型指令,而不是命令型指令,如果cpu有空閒寄存器,那麼register就生效,如果沒有空閒寄存器,那麼register無效。

例如: int b = 0; register b = 0; b = b + 1; b = b + 1;

mov b, 0 mov eax, 0 mov eax, b add eax, 1 add eax 1 mov b, eax

============================================================================= 字符串格式化輸出和輸入:

字符串在計算機內部的存儲方式:字符串是內存中一段連續的char空間,以 \0 結尾。

'a'     在內存裏就是一個字符a "a"    在內存裏是兩個連續的字符,第一個是'a',第二個是'\0' "hello world" 相當於 'h' 'e' ....... 'd' '\0' ----------------------------------------------------------------------------- 1、字符串格式化輸出: putchar    一次只能輸出一個char 例如:

putchar(100); //輸出的是ASCII d putchar('a');   //輸出的是 a putchar(\n');  //輸出的是 換行

printf       一次只能輸出一個字符串

例如:

printf("hello world\n"); //輸出的是 hello world int a = 100; printf(a);    //這樣是錯誤的,應該如下:

int a = 100; printf("%d\n", a); ----------------------------------------------------------------------------- printf的格式:       對應的數據類型:        含義: %d       int            輸出一個十進制的有符號的整數 %hd     short int        輸出有符號的短整數 %hu     unsigned short int   輸出無符號的短整數 %o       unsigned int       輸出無符號的8進制整數 %u       unsigned int       輸出無符號的10進制整數 %x        unsigned int       輸出無符號的16進制整數(abcdef) %X       unsigned int       輸出無符號的16進制整數(ABCDEF) %f        float或者double       輸出單精度浮點數/雙精度浮點數 %e/E      double           輸出科學計數法表示的數 %c       char          可以把輸入的數字按照ASCII相應轉換爲對應的字符 %s       char *          輸出字符串中的字符直至字符串中的空字符(字符串以'\0'結尾,這個'\0'即是空字符) %S       wchar t * %p        void *            以16進制形式輸出指針 %%       %            輸出一個百分號 例如: printf("%p\n", &a);       //&a 的意思是:取變量a在內存中的地址(輸出地址用 %p) ----------------------------------------------------------------------------- printf的附加格式: %l         ld、lu、lo、lx 表示長整數 %m       表示輸出數據的最小寬度,默認爲右對齊 %-        左對齊 %0       將輸出的前面補上0,直到佔滿指定列寬爲止(不可以搭配使用 - 哦) 例如: long int      用%ld long long int   用%lld

例如:

printf("(%6d)\n", a);       //輸出的是:(   100) printf("(%-6d)\n", a);     //輸出的是:(100   ) printf("(%06d)\n", a);    //輸出的是:(000100) ----------------------------------------------------------------------------- 2、字符串格式化輸入: getchar 函數:是從標準輸入設備讀取到一個char。需要包含頭文件stdio.h,返回值是一個int,不需要傳入參數。 scanf    函數:通過%d轉義的方式可以得到用戶通過標準輸入設備輸入的整數。

例如:

int a = getchar(); printf("%d\n", a);   //輸出對應的一個字符的ASCII,假如鍵盤輸入a,則輸出97

例如:

int a; scanf("%d", &a);   //特別注意:第二個參數是變量的地址,而不是變量本身 printf("%d\n", a);   //假如鍵盤輸入300,則輸出300

============================================================================= VS2013的C4996錯誤解決方法? 由於微軟在VS2013中不建議再使用c的傳統庫函數scanf,strcpy,sprintf等, 所以直接使用這些庫函數會提示C4996錯誤,在源文件中添加以下指令就可以避免這個錯誤提示: 法一: #define _CRT_SECURE_NO_WARNINGS 把這個宏定義一定要放到.c文件的第一行 法二: 在主函數任意一行加上 #pragma warning(disable:4996) 如下圖所示:

============================================================================= 基本運算符

%   取餘運算 int a = 7 % 2; printf("%d\n", a);   //輸出的是:1 ----------------------------------------------------------------------------- a += 3;   //相當於 a = a + 3; a -= 3;   //相當於 a = a - 3; a *= 3;   //相當於 a = a * 3; a /= 3;   //相當於 a = a / 3; ----------------------------------------------------------------------------- a++;   //相當於a += 1;或者a = a + 1; a--;     //相當於a -= 1;或者a = a - 1;

b = a++;  //先計算表達式的值,即先把a賦值給了b;然後a再自加1。 b = ++a;  //先a自加1後;然後把a自加後得到的賦值給b。 小結:誰在前面先計算誰!!!

例如: int a = 3; int b = a++;   //先計算表達式的值,即先把a的賦值給了b(b = a = 3);然後a再自加1(a = a + 1)。 printf("%d. %d\n",a, b); //輸出的是:4,3

int a = 3; int b = ++a;     //先a自加1得a = 4(a = a + 1),再把a的賦值給了b(b = a = 4) printf("%d. %d\n",a, b); //輸出的是:4,4 ----------------------------------------------------------------------------- 不同廠家的編譯器會有不同的結果: 在gcc的編譯下: int a = 3; int b = ++a + a++;    //輸出的是:5,9 int b = a++ + ++a;    //輸出的是:5,8 printf("%d. %d\n",a, b);

在VS2013的編譯下: int a = 3; int b = ++a + a++;    //輸出的是:5,8 int b = a++ + ++a;    //輸出的是:5,8 printf("%d. %d\n",a, b); ----------------------------------------------------------------------------- 逗號運算符:先計算逗號左邊的值,再計算逗號右邊的值,但整個語句的值是逗號右邊的值。 (爲什麼呢?要注意先計算逗號左邊的值是否對計算逗號右邊的值有影響) 例如: int a = 2; int b = 3; int c = 4; int d = 5; int i = (a = b, c + d);   //得到i的值爲:9

int a = 2; int b = 3; int c = 4; int d = 5; int i = (a = b, a + d);     //得到i的值爲:8 ----------------------------------------------------------------------------- 運算符的優先級

優先級編號      運算符                                             優先級一樣時: 1(優先級高)     []數組下標、()圓括號、()調用函數、{}語句塊                           從左到右運算 2                ++、--、+前綴、-前綴、!前綴、~前綴、sizeof、

          *取指針值、&取地址值、(type)類型轉換                                   從右到左運算(注意) 3            *、/、%取餘                                         從左到右運算 4            +、-                                                 從左到右運算 5           <<、>>                                           從左到右運算 6           <、>、<=、>=                                       從左到右運算 7           ==、!=                                         從左到右運算 8           &                                            從左到右運算 9           ^                                             從左到右運算 10         |                                           從左到右運算 11         &&                                               從左到右運算 12           ||                                                      從左到右運算 13         ?                                   從右到左運算(注意) 14         =、*=、%=、+=、-=、<<=、>>=、&=、|=、^=               從右到左運算(注意) 15(優先級低)      ,逗號運算符                                從左到右運算

注意:如果不能確定優先級,或者要改變默認的優先級,用()小括號。 ----------------------------------------------------------------------------- 類型轉換

double f = (double)5/2;      //強制轉換,把int的5強轉爲double類型的5.000000,輸出是:2.500000 double f = (double)(5/2);   //強制轉換,把int的5/int的2的結果強轉爲double類型,輸出是:2.000000

c語言約定: 1、兩個整數計算的結果也是一個整數 2、浮點數與整數計算的結果是浮點數,浮點數和浮點數計算的結果還是浮點數

=============================================================================

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章