1. 指針
1.1 自增符的使用
++*p;//p指向的內容加一
(*p)++; //p指向的內容加一
*p++;//p本身自增
*++p; //p本身自增
因為諸如*和++這樣的一元運算符在表達式求值時按從右到左的順序和運算分量結合。
1.2 指針運算比數組下標運算快
1.3 數組名
一個數組名即該數組第0個元素的位置,所以賦值語句pa = &a[0]等價於pa = a
1.4 數組下標求值
在求數組元素a[i]的值時,C語言實際上先將其轉換成*(a + i)的形式再求值
而對於指針pa而言,pa[i] 等價於 *(pa + i)
1.5 數組名與指向數組首地址的指針的區別
前者非變量,後者為變量
1.6 函數參數傳入指針
在函數的定義中,char s[]與char *s是等價的。
當函數參數傳入一個較大數組的子數組的指針時,並不會對函數本身造成影響
1.7 指針使用負下標
如果確信某個元素存在,則使用p[ -1]、p[ -2 ]這樣的表達式在語法上是合法的。
b[] = {,,,,,,,,, *a = b + ;
則:a[-3] = 1; a[ -2] = 2;
1.8 alloc與afree的棧式管理
先分配的後釋放
調用alloc之前:
allocbuf:
調用alloc之後:
allocbuf:
afree(p)是將空閒單元起始指針指向p位置
1.9 比較運算
在知道指針值意義的情況下,可以對其進行比較運算
b[] = {,,,,,,,,, *p1 = &b[ *p2 = &b[];
則p2 – p1 = 4
1.10 指針相關的有效運算
1.11 strcpy函數
原書上的函數:
strcpy( *s, *( *s++ = *t++
有錯誤,s的指針變量,雖然內容被復制的,但是找不到該段內容的首地址了,應該為:
*strcpy( *s, * *( *cp++ == *t++
1.12 函數參數為二維數組
f( int daytab[2][13])
= f(int daytab[][13])
=f(int (*daytab)[13])
傳入一個指針,指針每個元素的內容是一個數組
1.13指向數組的指針和指針數組
int (*daytab)[13] -->指針指向的內容是int[13]的數組
int *daytab[13]à13個指針指向int
指針的實質是根據定義的類型和其中存儲的地址來解析內存裡的數據
print (Int *s){
s[1] = 5;//即為*(s+1) = 5;
};
*(s+1) = 5;
根據指針所存的地址及所定義的類型,改變其中的數據
int (*daytab)[13]
所定義的類型為int[13]的數組
所以,對該指針解引用得到的是一段13個int長的內存區域的首地址
即:
int a[4][4]; int (*b)[4] = a;
b[2][2] = *(*(b+2)+2) = (*(s+2))[2] != *(s+2)[2]
分析:
*b解引用得到:int[4]
*b的值為這段int[4]的首地址
**b為這段int[4]首地址指向的內容即為b[0][0]的值
1.14 指針數組的初始化
即用指針來初始化數組
1.15 指向函數的指針
1.15.1 一個實例:
支持-n進行數字排序的排序函數
#include <stdio.h> #include <.h> MAXLINES 5000 /* max #lines to be sorted */ *lineptr[MAXLINES]; readlines( *lineptr[], writelines( *lineptr[], qsort( *lineptr[], left, (*comp)( *, * numcmp( *, * main( argc, * nlines; numeric = ; (argc > && strcmp(argv[], )== numeric = ((nlines = readlines(lineptr, MAXLINES)) >= qsort((**) lineptr, (int (*)(void*,void*))(numeric ? numcmp : strcmp)); } printf( }
qsort( *v[], left, ) swap( *v[], , (left >= right) ; swap(v, left, (left + right)/ last = (i = left+; i <= right; i++ ((*comp)(v[i], v[left]) < swap(v, ++ qsort(v, last+ }
1.15.2 指向函數的指針&返回為指針的函數
指向函數的指針:
int (*comp)(void *, void *);
返回為指針的函數:
int *comp(void *, void *);
C在編譯時,每個函數都有一個入口地址,該入口地址就是函數指針所指向的地址
有了指向函數的指針變量後,可用該指針變量調用函數
1.15.3 函數指針的定義
1.void (*f)(int x);
調用(*f)(x);
2.typedef int (*fun_ptr)(int,int);
fun_ptr max_func = max;
c = max_func(a,b);
1.15.4 函數指針數組
1.標准定義:
int (*op[2])(int,int);
2.強制類型轉換
定義為普通的int型指針數組
在要使用時,強制類型轉換為相應的函數指針類型
int *a;
int add(int a, int b);
a = add;
r = ((int (*)(int,int))(a))(numa,numb);
1.16復雜指針的理解
基本形式:
char (*(*x())[])()
*x()如上式5,表示返回值為指針的函數
剩余部分表述的就是所返回的指針的類型:
返回的指針類型如上式6,返回值char的函數指針數組
所以,
x是一個函數,該函數的返回值是一個指向類型為char的函數指針數組的指針
char (*(*x[3])())[5]
(*x[3])()如上式6為函數指針數組
其他的部分描述函數指針數組的返回值
所以,x是一個返回值為char[5]的長度為3的函數指針數組
2.內存布局
2.1數組的內存布局
int a[10];
內存是連續分配的相鄰區域
int *p = &a;
p = p + 1;
2.2 大端模式 & 小端模式
大端模式:即指數據的高位,保存在內存的低地址中,而數據的低位,保存在內存的高地址中
例:
65534(0x0000FFFE)
小端模式(一字節存儲單位):
0x0000 0x0008 0x0010 0x0018
FE FF 00 00
大端模式:
0x0000 0x0008 0x0010 0x0018
00 00 FF FE
3.結構
3.1 結構變量的定義方法
struct {…} x,y,z;
語法上與int x,y,z;相似
3.2 結構變量的定義方法
typedef struct{…} myType;
3.3 結構變量的初始化
struct point maxpt = {320,200};
3.4 對結構體的合法操作
3.5 結構數組的初始化
*= {“auto”,,””,};
3.6 字節對齊
參加博文《關於C語言中結構體中的結構體成員導致的字節對齊問題》
4.其他
4.1 逗號表達式
逗號運算符,優先級別最低,它將兩式連起來,其求解過程先表達式1,後表達式2,整個表達式是表達式2的值
(3+5,6+8) = 14
(a = 3*5,a*4) = 60
4.2 命令行參數
argc 程序執行時命令行中參數的數目
argv 指向字符串數組的指針
4.3 聯合
在單獨存儲區域中管理不同類型的數據
4.4 位字段
is_keyword : is_extern : is_static :
分配空間大小為flags分配字段類型最長的倍數,然後一個字節一個字節地存儲。在字節內的存儲方式未知,根據不同的編譯器決定從右往左還是從左往右。GCC是從右往左。