政府網(wǎng)站頁面設(shè)計標(biāo)準(zhǔn)win10優(yōu)化大師怎么樣
指針與數(shù)組
- 指針與數(shù)組
- 指針數(shù)組
- 數(shù)組指針
- 多維數(shù)組
- 數(shù)組名的保存
- 結(jié)構(gòu)體
- 定義結(jié)構(gòu)體
- 定義結(jié)構(gòu)體變量
- 使用typedef簡化結(jié)構(gòu)體聲明
- 訪問結(jié)構(gòu)體成員
- 結(jié)構(gòu)體內(nèi)存分配
- 字節(jié)對齊
- 位域
- 定義位域
- 位域的限制
- 示例
指針與數(shù)組
指針數(shù)組和數(shù)組指針是兩個不同的概念,它們涉及到指針和數(shù)組的組合使用。
指針數(shù)組
- 定義: 指針數(shù)組是一個數(shù)組,其中的每個元素都是一個指針。
- 示例:
int *ptrArray[5];
聲明了一個包含5個元素的指針數(shù)組,每個元素都是一個指向整數(shù)的指針。 - 用途: 指針數(shù)組常用于存儲一組指針,每個指針可以指向不同類型的數(shù)據(jù)或不同位置的數(shù)組。
#include <stdio.h>
int main()
{char a[5] = {'a', 'b', 'c', 'd', 'e'};char *p[5];printf("sizeof(a) = %d\n", sizeof(a));printf("sizeof(p) = %d\n", sizeof(p));return 0;
}
輸出
cd 'e:\CProject\output'
PS E:\CProject\output> & .\'指針數(shù)組.exe'
sizeof(a) = 5
sizeof(p) = 40
可以看到指針數(shù)組的大小是個數(shù)*對應(yīng)類型的指針的大小
舉例2
#include <stdio.h>
int main() {int a = 1, b = 2, c = 3;int *ptrArray[3] = {&a, &b, &c};// 打印指針數(shù)組中每個元素指向的值for (int i = 0; i < 3; i++) {printf("%d ", *ptrArray[i]);}return 0;
}
輸出
PS E:\CProject\output> cd 'e:\CProject\output'
PS E:\CProject\output> & .\'指針數(shù)組.exe'
1 2 3
在這個例子中,ptrArray
是一個包含3個指針的數(shù)組,每個指針分別指向整數(shù)變量 a
、b
和 c
。
數(shù)組指針
- 定義: 數(shù)組指針是一個指針,它指向一個數(shù)組。
- 示例:
int (*ptr)[5];
聲明了一個指針,指向包含5個元素的整數(shù)數(shù)組。 - 用途: 數(shù)組指針常用于處理二維數(shù)組或作為指向動態(tài)分配數(shù)組的指針。
#include <stdio.h>
int main() {int arr[3][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};int (*ptr)[5] = arr;// 打印數(shù)組指針指向的數(shù)組中的元素for (int i = 0; i < 3; i++) {for (int j = 0; j < 5; j++) {printf("%d ", ptr[i][j]);}printf("\n");}return 0;
}
在這個例子中,ptr
是一個指針,指向包含5個元素的整數(shù)數(shù)組,它被初始化為指向二維數(shù)組 arr
的第一行。
總體而言,指針數(shù)組和數(shù)組指針提供了在數(shù)組和指針之間靈活切換的方式,依賴于實際需求選擇使用哪一種形式。
多維數(shù)組
數(shù)組名的保存
- 定義一個指針,指向
int a[10];
的首地址 - 定義一個指針,指向
int b[5][6];
的首地址
#include <stdio.h>
int main()
{int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int b[3][4];int *p1 = a;int **p2 = b; // 這樣是錯誤的,二維數(shù)組和二維指針沒有關(guān)系return 0;
}
這樣是錯誤的,二維數(shù)組和二維指針沒有關(guān)系
二維數(shù)組是一行一行讀取的,一次就讀取4列的數(shù)據(jù)
二維指針是存儲線性的地址
正確的讀取方式
#include <stdio.h>
int main()
{int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int b[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};int *p1 = a;int(*p2)[4] = b; // 每次讀4個printf("%d\n\n", *p1);printf("%d\n", *p2[0]);printf("%d\n", *p2[1]);printf("%d\n", *p2[2]);return 0;
}
舉例2
int c[2][3][4];
int (*p)[3][4]; //T
結(jié)構(gòu)體
C語言中的結(jié)構(gòu)體(struct)是一種用戶自定義的數(shù)據(jù)類型,它允許你將不同類型的數(shù)據(jù)組合在一起。這使得你可以創(chuàng)建更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)來表示現(xiàn)實世界中的實體。一個結(jié)構(gòu)體可以包含多個成員(member),每個成員都有自己的數(shù)據(jù)類型和名稱。
下面是一些關(guān)于C語言結(jié)構(gòu)體的基本概念和用法:
定義結(jié)構(gòu)體
要定義一個結(jié)構(gòu)體,你需要使用struct
關(guān)鍵字,后跟結(jié)構(gòu)體的標(biāo)簽(可選),接著是花括號包圍的一系列成員聲明,最后以分號結(jié)束。
struct Point {int x;int y;
};
定義結(jié)構(gòu)體變量
一旦定義了結(jié)構(gòu)體,就可以聲明該結(jié)構(gòu)體類型的變量。有兩種方式來做這件事:
- 在定義結(jié)構(gòu)體的同時聲明變量:
struct Point pt1, pt2;
- 先定義結(jié)構(gòu)體,然后在其他地方聲明變量:
struct Point;// ... 之后某個地方struct Point pt1, pt2;
如果你給結(jié)構(gòu)體指定了標(biāo)簽(如上面例子中的Point
),那么可以在后續(xù)代碼中僅使用struct Point
來聲明新的變量。
使用typedef簡化結(jié)構(gòu)體聲明
為了簡化結(jié)構(gòu)體變量的聲明,通常會與typedef
一起使用:
typedef struct {int x;int y;
} Point;
這樣,以后可以直接使用Point
作為類型名來聲明結(jié)構(gòu)體變量,而不需要再寫struct Point
。
訪問結(jié)構(gòu)體成員
結(jié)構(gòu)體成員通過點運算符.
來訪問:
pt1.x = 10;
pt1.y = 20;
如果結(jié)構(gòu)體是指針,則使用箭頭運算符->
來訪問成員:
Point *p = &pt1;
p->x = 30; // 等價于 (*p).x = 30;
結(jié)構(gòu)體內(nèi)存分配
結(jié)構(gòu)體變量的內(nèi)存是在聲明時分配的。如果你需要動態(tài)分配結(jié)構(gòu)體的內(nèi)存,可以使用malloc()
或calloc()
函數(shù)。
Point *p = (Point *)malloc(sizeof(Point));
if (p != NULL) {p->x = 40;p->y = 50;
}
// 使用完后記得釋放內(nèi)存
free(p);
字節(jié)對齊
#include <stdio.h>struct student
{char x; // 4 字節(jié)對齊int roll; // 4float marks; // 4
};
int main()
{struct student s1;printf("struct size: %d\n", sizeof(s1));return 0;
}
字節(jié)對齊:為了效率,希望犧牲一點空間換取時間的效率
分別看一下定義的順序不同,占用的空間大小!
#include <stdio.h>struct student
{char x; // 2short y; // 2int roll; // 4
};struct stu
{char x; // 4int roll; // 4short y; // 4
};
int main()
{struct student s1;printf("struct size: %d\n", sizeof(s1));struct stu s2;printf("struct size: %d\n", sizeof(s2));return 0;
}
由于定義的順序不同,占用的空間大小也不同!
第一種定義方式里,char剩余3bytes,可以給short類型的變量使用,如下圖所示:
第二種定義的順序,在內(nèi)存中的分布如下
位域
位域(bit-fields)是C語言中的一種特殊結(jié)構(gòu)體成員,它允許你定義一個特定寬度的字段,以位為單位。位域主要用于需要緊湊存儲或與硬件通信的場合,比如嵌入式系統(tǒng)編程。
在位域中,你可以指定每個成員占用的位數(shù),這可以減少內(nèi)存的使用量。然而,使用位域也可能會導(dǎo)致代碼的可移植性問題,因為不同的編譯器可能對位域的實現(xiàn)有所不同,包括它們?nèi)绾未虬蛯R數(shù)據(jù)。
定義位域
位域通過在結(jié)構(gòu)體成員聲明后添加冒號和位寬來定義。以下是位域的一個簡單例子:
struct packed_struct {unsigned int f1 : 1; // 1 bitunsigned int f2 : 3; // 3 bitsunsigned int f3 : 4; // 4 bits
};
在這個例子中,packed_struct
包含三個位域成員:f1
、f2
和 f3
,分別占據(jù)1位、3位和4位。請注意,位域成員必須是整數(shù)類型(如int
、unsigned int
等),并且不能是數(shù)組或指針。
位域的限制
- 位域的大小:位域的最大寬度取決于底層整型的大小。例如,在大多數(shù)系統(tǒng)上,
unsigned int
通常是32位,所以你不能創(chuàng)建超過32位的位域。 - 匿名位域:有時會看到不帶名稱但帶有寬度的位域,這樣的位域用于填充或者對齊。例如,
unsigned int : 2;
將占用2位,但沒有關(guān)聯(lián)的變量名。 - 不可尋址性:由于位域是由多個位組成的,因此不能取位域成員的地址。
- 端序依賴:不同體系結(jié)構(gòu)上的字節(jié)順序(大端或小端)會影響位域的實際布局。
示例
這里有一個更完整的示例,展示了如何使用位域:
#include <stdio.h>struct Flags {unsigned int flag1 : 1;unsigned int flag2 : 1;unsigned int : 6; // 匿名位域,用于填充或?qū)Runsigned int flag3 : 1;
};int main() {struct Flags flags;flags.flag1 = 1;flags.flag2 = 0;flags.flag3 = 1;printf("flag1: %d\n", flags.flag1);printf("flag2: %d\n", flags.flag2);printf("flag3: %d\n", flags.flag3);return 0;
}
這個程序定義了一個Flags
結(jié)構(gòu)體,其中包含了三個標(biāo)志位,每個都只占用了1位。注意,我們還插入了一個6位的匿名位域,用于確保后續(xù)的位域從一個新的字節(jié)開始(假設(shè)編譯器按照8位邊界對齊)。
請記住,盡管位域提供了一種節(jié)省空間的方法,但在編寫代碼時應(yīng)該考慮到它的可移植性和潛在的復(fù)雜性。如果你不需要精確控制位級別的數(shù)據(jù),通常最好使用普通的結(jié)構(gòu)體成員。
【嵌入式C語言】 https://www.bilibili.com/video/BV1RW411G7cr/?p=44&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933