数据类型与变量
- 数据类型
- 类型相同的数据具有相同的表示形式、存储格式和操作,程序中所以数据必须属于某种数据类型。
- 为编译器提供分配内存大小的依据,数据类型本身没有内存空间。
- 使用
typedef
给类型起别名方便使用。
-
void
:无类型,用来定义指针 void *p
,函数返回值,函数参数。
#include
int main(int argc, char const *argv[])
{
int arr[] = {1, 2, 3};
printf("%d\n", sizeof(arr)); // 12
// arr = 6422308 arr + 1 = 6422312
// arr 表示数据手元素地址 + 1 加的是一个元素的长度4
printf("arr = %d arr + 1 = %d\n", arr, arr + 1);
// &arr = 6422308 &arr + 1 = 6422320
// &arr 表示的是整个数组的首地址 + 1,加整个数组的长度12
printf("&arr = %d &arr + 1 = %d\n", &arr, &arr + 1);
return 0;
}
- 变量:变量的使用要抓住生命周期和作用域两点。
- 全局变量(包括静态(文件内使用),普通(可跨文件使用))。
- 局部变量(函数中的变量,形参,函数内使用)。
- 生命周期伴随程序结束:静态变量(包括全局和局部,存放在data区),全局变量。
- 函数执行完成销毁:局部变量,形参。
- 有些局部变量指向堆区地址,在函数执行结束时,形参销毁但是堆区地址不会自动回收,只有
free()
函数回收。
内存分区(stack、heap、data、bss、text)
-
stack
:栈区,存放函数执行过程中的局部变量和形参,函数调用完毕释放。
- 栈区地址由高向低使用,栈区有一定的大小限制,超过会造成堆栈溢出问题。
指针、函数指针
- 数组在作为形参时会退化为指针,在接收数组参数时,形参可以直接写指针形式。
#include
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("数组的长度为:%d\n", sizeof(arr)); // 12(int * 3)
printf("func 数组形参的长度为:%d\n", func(arr)); // 4 32位系统中一个指针的长度
printf("func1 数组形参的长度为:%d\n", func1(arr)); // 4
printf("func2 数组形参的长度为:%d\n", func2(arr)); // 4
return 0;
}
- 指针是大小固定(与编译器决定)的数据类型。
- 指针变量存储一个地址,它通过这个地址访问对应的地址块。
- 二级指针做形参,接收一个一级指针的地址。
#include
#include
#include
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;
}
字符串处理
- 函数接收字符串数组。
#include
#include
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()
是运算符,不是函数,sizeof()
部分在编译之前就已经确定结果。
#include
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
类型指针的长度,但是无法求得void
类型变量的长度。因为这样的变量无法分配内存大小,所以你也定义不了。但是指针是存储的一个地址,地址是根据编译器的位数决定的,所以指针的大小是确定的,比如32位编译器分配的指针就是4个字节的大小。
#include
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()
求静态分配内存的数组的大小
#include
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
// 字符串数组,默认结尾加上结束符'\0'
char str_arr[] = "hgz";
printf("str_arr_len = %d\n", sizeof(str_arr)); // str_arr_len = 4
// 数组作为函数参数,形参退化成指针,提高运行效率
printf("arr_arg_len = %d\n", func(int_arr)); // arr_arg_len = 4
return 0;
}
数组
- 指针数组,数组里面存储指针类型的变量。
#include
int main(int argc, char const *argv[])
{
int i = 0;
// 指针数组,数组里面存储指针类型
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;
}
- 数组指针,指向整个数组的指针,而不是首元素。
#include
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 步长是一个数组的大小
printf("p = %d p + 1 = %d\n", p, p+1);
// 定义数组指针类型
int(*q)[10];
q = &arr;
printf("%d\n", q);
return 0;
}
- 二维数组
#include
int main(int argc, char const *argv[])
{
int arr[][2] = {{1, 2}, {3, 4}, {5, 6}};
// 差8个字节,步长为一行
printf("arr = %d arr+1 = %d\n", arr, arr+1);
// 差24字节,步长为整个二维数组的长度
printf("&arr = %d &arr+1 = %d\n", &arr, &arr+1);
return 0;
}