相较于基本型別int, double,C语言还有衍伸資料型別(Derived datatype)。
留言
其中很常被应用的,就是指標(pointer)、陣列(Array)、結構(struct)
指标(Pointer)
指标的设计,是为了让CPU可以间接取得资料,有以下优点:
可动态配置/释放记忆体
不同的函式可共享大量的储存空间
改善程式存取资料的效率
指标的特性
指标本身是一个物件,指向任何一个已存在物件,可以被指定或拷贝
指标宣告时,就要定义是指向哪种资料型态的物件
指标本身储存的值,有三种情况
指向一个物件,值里面存放另一个物件的位址
指向另一个物件尾端后的位置
没有指向任何物件,值即为null
int i = 42;
int *p = &i; //p指向i
#include <stdio.h>
int main() {
int i = 42;
int *p; //* 跟在一个型别,且是宣告的一部份,所以p是一个pointer
p = &i; //p指向i
printf("i: %d\n", i);
printf("*p: %d\n", *p);
printf("p: %p\n", p);
printf("&i: %p\n", &i);
return 0;
}
阵列(Array)
留言
阵列的定义
是一个复合资料型别,放置单一型别物件的容器,并且以位置来存取它们,有固定的尺寸。
通常是存放char,int型别的资料
字元阵列的特性
在C语言,一个字串本身会在结尾自带\0结束字元,所以当我们把一个字串用阵列储存时,实际结尾会有一个\0也被储存。
例如:char str[20] = "Hello"
在阵列的存放,是一个长度为6的阵列,最后摆放\0
宣告与初始化阵列
靜態宣告
int a[10]; //宣告一个10个int物件的阵列
int *p[10]; //宣告一个10个int指标的阵列
因为阵列的长度要在编译期就决定好。如果想要在执行期动态生成阵列,要用动态配置记忆体的方式。
动态宣告
我们同样用malloc() 函式来配置记忆体。参考以下叙述:
int *arr = (int *) malloc(sz * sizeof(int));
我们以sizeof 求得单一元素的大小后,乘上阵列的长度sz 即可配置一块足够大小的记忆体,用来储存阵列arr 的元素。由此可知,阵列在电脑中以是一整块连续的记忆体来储存,所以可以用索引值快速存取。
留言
如果想要在配置记忆体时一并将元素初始化为0,改用calloc() 函式即可。但calloc() 函式的参数略有不同:
int *arr = (int *) calloc(sz, sizeof(int));
由于多了初始化的动作,calloc() 函式会比malloc() 函式慢一点点。
留言
使用完后同样要释放记忆体:
free(arr);
由于阵列内部是单一且连续的记忆体区块,所以可在单一free() 函式呼叫中释放掉。不论使用malloc() 或calloc(),皆使用free() 来释放记忆体。
我们来看一个动态配置记忆体阵列的范例:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int size = 0;
printf("输入长度:");
scanf("%d", &size);
int *arr = malloc(size * sizeof(int));
printf("指定元素:\n");
for(int i = 0; i < size; i++) {
printf("arr[%d] = ", i);
scanf("%d" , arr + i);
}
printf("显示元素:\n");
for(int i = 0; i < size; i++) {
printf("arr[%d] = %d\n", i, *(arr+i));
}
free(arr);
return 0;
}
存取阵列元素
阵列使用零或正整数存取阵列元素。参考以下范例:
#include <stdio.h>
int main(void)
{
int arr[] = {3, 4, 5};
printf("%d", arr[0]);
printf("%d", arr[1]);
printf("%d", arr[2]);
return 0;
}
指标算术
对一个指标做加减,会移动指向阵列中的位置
#include <stdio.h>
int main(void)
{
int arr[] = {3, 4, 5, 6, 7};
for (int i = 0; i < 5; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
计算阵列大小
C 阵列本身没有储存阵列大小的资讯。如果想要知道阵列的大小,得自行计算。参考下例:
#include <stdio.h>
int main(void)
{
int arr[] = {3, 4, 5, 6, 7};
int sz = sizeof(arr) / sizeof(int);
printf("%d", sz);
return 0;
}
在此范例程式中,我们在第6 行分别计算阵列大小和阵列元素大小,将其相除后即可得阵列长度。在本例中其值为5。
留言
但这个方式只对自动配置记忆体的阵列有效,若阵列使用动态配置记忆体,则无法使用这个方法。
多维阵列
先前的范例皆为一维阵列,但C 语言允许多维阵列。参考以下宣告多维阵列的叙述:
int mtx[3][2] = {
{1, 2},
{3, 4},
{5, 6}
};
我們同樣可以對多維陣列存取索引值:
#include <stdio.h>
int main(void)
{
int mtx[3][2] = {
{1, 2},
{3, 4},
{5, 6}
};
printf("%d\n", mtx[1][1]);
return 0;
}
结构(struct)
宣告struct
结构(struct)可以让使用者创造自己定义的资料型别
例如一本书的销售资讯包含多种资料:
struct Sales_data {
char* book_no;
int units_sold;
int price;
double revenue;
};
其中book_no, units_sold , price,revenue是这个struct的data members,简称members
呼叫struct
#include <stdio.h>
struct Sales_data {
char* book_no;
int units_sold;
int price;
double revenue;
};
int main() {
struct Sales_data book1;
book1.book_no = "AAA";
book1.units_sold = 1000;
book1.price = 200;
book1.revenue = book1.units_sold * book1.price;
printf("Revenue: %.2f\n", book1.revenue);
return 0;
}