《C和指针》读书笔记
生活随笔
收集整理的這篇文章主要介紹了
《C和指针》读书笔记
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
看過了經典的K&R C,又看了這本Pointers on C,溫習了C語言的基本語法。
在重溫過程中,感覺需要重點把握的知識是指針、結構和動態內存分配。
這對今后的算法和操作系統方面的研究學習很有幫助。
int* b, c, d;
本以為這條語句把三個變量聲明為整型的指針,但事實并非如此。 星號*只對b有用,其余兩個變量只是普通的整型。正確語句:int *b, *c, *d;
3.3 typedef
允許為各種數據類型定義新名字。 #define無法正確地處理指針類型,如下: #define d_ptr_to_char char * d_ptr_to_char a, b; 只正確地聲明了a,但是b卻被聲明為一個字符。
3.4 常量
int const *pci; ? ? // 一個指向整型常量的指針 int * const cpi; ? ?// 一個指向整型的常量指針
5.4.4 優先級和求值的順序
兩個相鄰操作符的執行順序由它們的優先級決定。 如果它們的優先級相同,它們的執行順序由它們的結合性決定。 除此之外,編譯器可以自由決定使用任何順序對表達式進行求值。
5.8 問題
2.下面程序的結果是什么?
int func(void) { static int counter = 1; return ++counter; }
int main() { int answer; answer = func() - func() * func(); printf("$d\n", answer); }
6.13 指針運算
當一個指針和一個整數執行算術運算時,整數在執行加法運算前始終會根據合適的大小進行調整。 即把整數量乘以指針所指向類型的大小。
指針 +/- 整數
指針 - 指針 只有當兩個指針都指向同一個數組中的元素時,才允許從一個指針減去另一個指針。
< <= > >= 可以在兩個任意的指針間執行相等或不等測試。
7.2 函數聲明
如果沒有關于調用函數的特定信息,編譯器便假定在這個函數的調用時參數的類型和數量是正確的。它同時會假定函數將返回一個整型值。如果編譯器認定函數返回一個整型值,它將產生整數指令操縱這個值。 float f; f = xyz(); xyz的返回值會被假定為整型,當成整型返回然后轉換成浮點型。
7.5 遞歸
許多教科書都把計算階乘和斐波那契數列用來說明遞歸,這是非常不幸的。在第1個例子里,遞歸并沒有提供任何優越之處。在第2個例子中,它的效率之低是非常恐怖。
8.1 一維數組
對于int類型的數組,數組名的類型就是“指向int的常量指針”。 int a[10]; int *c; a = c; ? ? // error
int ap[10];
ap:指針變量中的值,即數組的起始地址。 *ap:ap[0] ap[0] ap + 6:數組地址加6,即第6個元素的地址。 *ap + 6:ap[0]+6 *(ap + 6):ap[6]
9.2 字符串長度
size_t strlen(char const *string);
注意strlen返回一個類型為size_t(無符號整型)的值。在表達式中使用無符號數可能導致不可預料的結果。 if ( strlen(x) >= strlen(y) ) ... if ( strlen(x) - strlen(y) >= 0) ... 第1條語句能按照你預想的那樣工作,第2條語句的結果將永遠為真。>=左邊的表達式將是無符號數,而 無符號數絕不可能是負的。 類似的: if ( strlen(x) >= 10) ... if ( strlen(x) - 10 >= 0) ... 原因同上。
9.3 不受限制的字符串函數
復制:char *strcpy(char *dst, char const *src); 拼接:char *strcat(char *dst, char const *src); 比較:int strcmp(char const *s1, char const *s2); 注意常見錯誤:if(strcmp(a, b))。以為如果兩個字符串相等,它的結果將是真。恰恰相反。
9.5 字符串查找基礎
查找一個字符 char *strchr(char const *str, int ch); char *strrchr(char const *str, int ch);
char string[20] = "Hello there, honey." char *ans; ans = strchr(string, 'h'); ? ? // ans=string+7
查找任何幾個字符 char *strpbrk(char const *str, char const *group);
ans = strpbrk(string, "aeiou"); ? ? // ans=string+1
查找一個子串 char *strstr(char const *s1, char const *s2); 這個函數在s1中查找整個s2第1次出現的起始位置,并返回一個指向該位置的指針。
9.9 內存操作
void *memcpy(void *dst, void const *src, size_t length); 和strn開頭的函數不同,它們在遇到NUL字節時并不會停止操作。
char temp[SIZE], values[SIZE]; memcpy(temp, values, SIZE); ? ? // 復制char數組
int temp[SIZE], values[SIZE]; memcpy(temp, values, sizeof(values)); ? ? // 復制int數組要考慮移植性
int temp[5], values[SIZE]; memcpy(temp, values, 5 * sizeof(values[0])); ? ? // 復制int數組的前5個元素
10.1 結構基礎知識
struct SIMPLE { int ? ? ? ? a; char ?????b; float ?????c; }; struct SIMPLE x; struct SIMPLE y[20], *z;
也可以將結構創建成一種新的類型。
typedef struct { int ?????a; char ? ?b; float ? ?c; } Simple; Simple x; Simple y[20], *z;
結構的自引用 struct SELF_REF2 { int ? ? a; struct SELF_REF2 *b; int ? ? c; } A;
如果聲明struct SELF_REF2 b;則此結構定義是非法的。因為編譯器在結構的長度確定之前就已經知道指針的長度,所以聲明成指針才是合法的。
訪問方式:*(A.b).a 或 A->b.a
10.3 結構的存儲分配
struct ALIGN { char a; int ? ?b; char c; };
編譯器按照成員列表的順序一個接一個地給每個成員分配內存,可以在聲明中對結構的成員列表重新排列。
struct ALIGN2 { int ? ?b; char a; char c; };
10.4 作為函數參數的結構
void f(struct ALIGN a); ? ? // 調用函數時要拷貝整個結構到棧中 void f(struct ALIGN *a); ? ?// 只傳遞4字節的指針
10.5 位段
struct CHAR { unsigned ch : 7; unsigned font : 6; unsigned size : 19; } ch1;
size位段過大無法容納于一個短整型,但其余位段都比一個字符還短。 位段使程序員能夠利用存儲ch和font所剩余的位來增加size的位數,避免聲明 一個32位的正數來存儲size位段。
訪問磁盤控制器的例子,假設其地址為0xc0200142。
struct DISK_REGISTER_FORMAT { unsigned ? ? command ? ? : 5; unsigned ? ? sector ? ? ? ? ?: 5; unsigned ? ? track ? ? ? ? ? ?: 9; ... unsigned ? ? ready ? ? ? ? ? : 1; };
#define DISK_REGISTER ((struct DISK_REGISTER_FORMAT *) 0xc0200142)
// 告訴控制器從哪個扇區哪個磁道開始讀取 DISK_REGISTER->sector = new_sector; DISK_REGISTER->track ? = new_track; DISK_REGISTER->command = READ;
while ( !DISK_REGISTER->ready) ;
10.6 聯合
union { float ? ? f; int ? ? ? ?i; } fi;
fi.f = 3.14159; printf("%d\n", fi.i);
首先把π的浮點表示形式存儲于fi,然后把這些相同的位當做一個整型值打印輸出。
11.1 - 3
malloc: void *malloc(size_t size); void free(void *pointer); 這些函數維護一個可用內存池。當一個程序另外需要一些內存時,malloc從 內存池中提取一塊合適的內存。
calloc: void *calloc(size_t num_elements, size_t element_size); calloc在返回指向內存的指針之前把它初始化為0。
realloc: void realloc(void *ptr, size_t new_size); 如果原先的內存塊無法改變大小,realloc將分配另一塊正確大小的內存, 并把原先那塊內存的內容復制到新的塊上。
11.5 常見的內存錯誤
1. 忘記檢查所請求的內存是否成功分配。
int *pi; pi = malloc(100); if (pi == NULL) { printf("Out of memory!\n"); exit(1); }
2. 操作內存時超出了分配內存的邊界。
3. 傳給free函數一個指針,讓它釋放一塊并非動態分配的內存。 試圖釋放一塊動態分配內存的一部分也有可能出錯。
pi = malloc(10 * sizeof(int)); free(pi + 5);
4. 內存泄露
轉載于:https://www.cnblogs.com/xiaomaohai/archive/2012/02/04/6157871.html
總結
以上是生活随笔為你收集整理的《C和指针》读书笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Stata数据处理:清洗中国城市建设统计
- 下一篇: oracle调整Lock_sga参数而不