數(shù)據(jù)類(lèi)型與變量
- 數(shù)據(jù)類(lèi)型
- 類(lèi)型相同的數(shù)據(jù)具有相同的表示形式晕翠、存儲(chǔ)格式和操作叹阔,程序中所以數(shù)據(jù)必須屬于某種數(shù)據(jù)類(lèi)型。
- 為編譯器提供分配內(nèi)存大小的依據(jù)镀虐,數(shù)據(jù)類(lèi)型本身沒(méi)有內(nèi)存空間屹培。
- 使用
typedef
給類(lèi)型起別名方便使用默穴。
-
void
:無(wú)類(lèi)型,用來(lái)定義指針 void *p
,函數(shù)返回值惫谤,函數(shù)參數(shù)壁顶。
#include <stdio.h>
int main(int argc, char const *argv[])
{
int arr[] = {1, 2, 3};
printf("%d\n", sizeof(arr)); // 12
// arr = 6422308 arr + 1 = 6422312
// arr 表示數(shù)據(jù)手元素地址 + 1 加的是一個(gè)元素的長(zhǎng)度4
printf("arr = %d arr + 1 = %d\n", arr, arr + 1);
// &arr = 6422308 &arr + 1 = 6422320
// &arr 表示的是整個(gè)數(shù)組的首地址 + 1,加整個(gè)數(shù)組的長(zhǎng)度12
printf("&arr = %d &arr + 1 = %d\n", &arr, &arr + 1);
return 0;
}
- 變量:變量的使用要抓住生命周期和作用域兩點(diǎn)溜歪。
- 全局變量(包括靜態(tài)(文件內(nèi)使用)若专,普通(可跨文件使用))。
- 局部變量(函數(shù)中的變量蝴猪,形參调衰,函數(shù)內(nèi)使用)。
- 生命周期伴隨程序結(jié)束:靜態(tài)變量(包括全局和局部自阱,存放在data區(qū))嚎莉,全局變量。
- 函數(shù)執(zhí)行完成銷(xiāo)毀:局部變量沛豌,形參趋箩。
- 有些局部變量指向堆區(qū)地址赃额,在函數(shù)執(zhí)行結(jié)束時(shí),形參銷(xiāo)毀但是堆區(qū)地址不會(huì)自動(dòng)回收叫确,只有
free()
函數(shù)回收跳芳。
內(nèi)存分區(qū)(stack、heap竹勉、data飞盆、bss、text)
-
stack
:棧區(qū)次乓,存放函數(shù)執(zhí)行過(guò)程中的局部變量和形參吓歇,函數(shù)調(diào)用完畢釋放。
- 棧區(qū)地址由高向低使用票腰,棧區(qū)有一定的大小限制城看,超過(guò)會(huì)造成堆棧溢出問(wèn)題。
指針丧慈、函數(shù)指針
- 數(shù)組在作為形參時(shí)會(huì)退化為指針析命,在接收數(shù)組參數(shù)時(shí)主卫,形參可以直接寫(xiě)指針形式逃默。
#include <stdio.h>
int func(int arr[]){
return sizeof(arr);
}
int func1(int arr[3]){
return sizeof(arr);
}
int func2(int *arr){
return sizeof(arr);
}
int main(int argc, char const *argv[])
{
int arr[3] = {1, 2, 3};
printf("數(shù)組的長(zhǎng)度為:%d\n", sizeof(arr)); // 12(int * 3)
printf("func 數(shù)組形參的長(zhǎng)度為:%d\n", func(arr)); // 4 32位系統(tǒng)中一個(gè)指針的長(zhǎng)度
printf("func1 數(shù)組形參的長(zhǎng)度為:%d\n", func1(arr)); // 4
printf("func2 數(shù)組形參的長(zhǎng)度為:%d\n", func2(arr)); // 4
return 0;
}
- 指針是大小固定(與編譯器決定)的數(shù)據(jù)類(lèi)型。
- 指針變量存儲(chǔ)一個(gè)地址簇搅,它通過(guò)這個(gè)地址訪(fǎng)問(wèn)對(duì)應(yīng)的地址塊完域。
- 二級(jí)指針做形參,接收一個(gè)一級(jí)指針的地址瘩将。
- 在使用指針類(lèi)型形參時(shí)吟税,要先做判斷,防止段錯(cuò)誤姿现。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(char **p, int *len){
if(p == NULL || len == NULL){
return;
}
char *temp = (char *)malloc(100);
strcpy(temp, "hgzzz");
*p = temp;
*len = strlen(temp);
}
int main(int argc, char const *argv[])
{
char *p = NULL;
int len = 0;
func(&p, &len);
printf("%s %d\n", p, len); // hgzzz 5
return 0;
}
字符串處理
- 函數(shù)接收字符串?dāng)?shù)組肠仪。
#include <stdio.h>
#include <string.h>
void print_arr(char **str_arr ,int len){
if(str_arr == NULL){
return;
}
int i;
for(i = 0; i < len; i++){
printf("%s ", str_arr[i]);
}
}
void sort_arr(char **str_arr ,int len){
if(str_arr == NULL) {
return;
}
int i,j;
char *temp;
for(i = 0; i < len - 1; i++){ // 快速排序
for(j = i + 1; j < len; j++){
if(strcmp(str_arr[i], str_arr[j]) > 0){
temp = str_arr[i];
str_arr[i] = str_arr[j];
str_arr[j] = temp;
}
}
}
}
int main(int argc, char const *argv[])
{
char *str_arr[] = { "aaa", "vvv", "ccc", "bbb" };
int len = sizeof(str_arr) / sizeof(str_arr[0]);
printf("排序前\n"); // aaa vvv ccc bbb
print_arr(str_arr, len);
sort_arr(str_arr, len);
printf("\n排序后\n"); // aaa bbb ccc vvv
print_arr(str_arr, len);
printf("\n");
return 0;
}
sizeof()
-
sizeof()
是運(yùn)算符,不是函數(shù),sizeof()
部分在編譯之前就已經(jīng)確定結(jié)果备典。
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a;
printf("int_len = %d\n", sizeof(a)); // int_len = 4
char *p;
printf("pointer_len = %d\n",sizeof(p)); // pointer_len = 4
return 0;
}
-
sizeof()
可以求得void
類(lèi)型指針的長(zhǎng)度异旧,但是無(wú)法求得void
類(lèi)型變量的長(zhǎng)度。因?yàn)檫@樣的變量無(wú)法分配內(nèi)存大小提佣,所以你也定義不了吮蛹。但是指針是存儲(chǔ)的一個(gè)地址,地址是根據(jù)編譯器的位數(shù)決定的拌屏,所以指針的大小是確定的潮针,比如32位編譯器分配的指針就是4個(gè)字節(jié)的大小。
#include <stdio.h>
int main(int argc, char const *argv[])
{
/*
void a; // error: variable or field 'a' declared void
printf("void_variable_len = %d\n", sizeof(a));
*/
void *p;
printf("void_pointer_len = %d\n", sizeof(p)); // void_pointer_len = 4
}
-
sizeof()
求靜態(tài)分配內(nèi)存的數(shù)組的大小
#include <stdio.h>
int func(int arr[2]){
return sizeof(arr);
}
int main(int argc, char const *argv[])
{
int int_arr[2] = {0};
printf("int_arr_len = %d\n", sizeof(int_arr)); // int_arr_len = 8
char char_arr[3] = {'a', 'b', 'c'};
printf("char_arr_len = %d\n", sizeof(char_arr)); // char_arr_len = 3
// 字符串?dāng)?shù)組倚喂,默認(rèn)結(jié)尾加上結(jié)束符'\0'
char str_arr[] = "hgz";
printf("str_arr_len = %d\n", sizeof(str_arr)); // str_arr_len = 4
// 數(shù)組作為函數(shù)參數(shù)每篷,形參退化成指針,提高運(yùn)行效率
printf("arr_arg_len = %d\n", func(int_arr)); // arr_arg_len = 4
return 0;
}
數(shù)組
- 指針數(shù)組,數(shù)組里面存儲(chǔ)指針類(lèi)型的變量焦读。
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i = 0;
// 指針數(shù)組带兜,數(shù)組里面存儲(chǔ)指針類(lèi)型
char *str_arr[] = {"aaa", "bbb", "ccc"};
for(i = 0; i < sizeof(str_arr)/sizeof(str_arr[0]); i++){
printf("%s\n", str_arr[i]);
printf("%d\n", sizeof(str_arr[i])); // 4
}
return 0;
}
- 數(shù)組指針,指向整個(gè)數(shù)組的指針吨灭,而不是首元素刚照。
#include <stdio.h>
int main(int argc, char const *argv[])
{
int arr[10] = {0};
typedef int int_arr_10[10];
int_arr_10 *p = NULL;
p = &arr;
// p = 6422276 p + 1 = 6422316 步長(zhǎng)是一個(gè)數(shù)組的大小
printf("p = %d p + 1 = %d\n", p, p+1);
// 定義數(shù)組指針類(lèi)型
int(*q)[10];
q = &arr;
printf("%d\n", q);
return 0;
}
- 二維數(shù)組
#include <stdio.h>
int main(int argc, char const *argv[])
{
int arr[][2] = {{1, 2}, {3, 4}, {5, 6}};
// 差8個(gè)字節(jié),步長(zhǎng)為一行
printf("arr = %d arr+1 = %d\n", arr, arr+1);
// 差24字節(jié)喧兄,步長(zhǎng)為整個(gè)二維數(shù)組的長(zhǎng)度
printf("&arr = %d &arr+1 = %d\n", &arr, &arr+1);
return 0;
}