对指针概念掌握的测试:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
///
//第一组
//
char arr[] = {'a', 'b', 'c', 'd', 'e', 'f'};
printf("%d\n", sizeof(arr)); //6 整个数组的内存大小
printf("%d\n",sizeof(arr + 0));//4 arr + 4是一个指针
printf("%d\n",sizeof(*arr));//1 *arr 得到一个字符char
printf("%d\n",sizeof(arr[1]));//1 arr[1]得到一个char
//&arr 类型是 char(*)[6]
printf("%d\n", sizeof(&arr));// 4 &arr得到的是一个数组指针也是指针
printf("%d\n", sizeof(&arr[0] + 1));// 4 得到的是一个char*
// strlen 是求字符串的长度,一个带 \0 的字符数组才叫字符串
printf("%d\n",strlen(arr));//未定义行为
printf("%d\n", strlen(arr + 0));//未定义行为
printf("%d\n", strlen(*arr));//char*指针.存了一个整数,整数是一个地址;char就是一个字符.
printf("%d\n", strlen(arr[1]));//同上
printf("%d\n", strlen(&arr));//&arr类型和char*不一致.如果隐式类型转换过去的话
//就会得到一个指向'a'指针.如果从这个指针往后找\0仍然找不到依然是一个未定义行为.
printf("%d\n", strlen(&arr + 1));//这个代码同上,一个数组指针加一跳过这个数组往后找\0,
//依旧未定义
printf("%d\n", strlen(&arr[0] + 1));//得到一个指向b的指针仍然未定义.
///
//第二组
//
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7 带 \0
printf("%d\n", sizeof(arr + 0));//4 arr + 0得到一个char*指针
printf("%d\n", sizeof(*arr));//1 *arr得到一个字符
printf("%d\n", sizeof(arr[1]));//1 同上
printf("%d\n", sizeof(&arr));//4 &arr得到一个数组指针
printf("%d\n", sizeof(&arr + 1));//4 同上
printf("%d\n", sizeof(&arr[0] + 1));//4 得到一个char*
printf("%d\n", strlen(arr));//6 strlen不算 \0
printf("%d\n", strlen(arr + 0));//6 得到的还是一个指向a的指针
printf("%d\n", strlen(*arr));//未定义行为 *arr得到的是字符a
printf("%d\n", strlen(arr[1]));//未定义行为 同上
printf("%d\n", strlen(&arr));//6 &arr是一个数组指针,里面存的地址恰好是数组首元素地址
printf("%d\n", strlen(&arr + 1));//未定义行为,&arr是个数组指针,给他+1,跳到数组后面去了,访问非法内存
printf("%d\n", strlen(&arr[0] + 1));//5 &arr[0] + 1 得到指向 b 的指针
///
//第三组
//
char* p = "abcdef";
printf("%d\n", sizeof(p));//4
printf("%d\n", sizeof(p + 1));//4
printf("%d\n", sizeof(*p));//1 *p是一个 char 类型
printf("%d\n", sizeof(p[1]));//1 p[1] 是一个char
printf("%d\n", sizeof(&p));//4 char**
printf("%d\n", sizeof(&p + 1));//4 char**
printf("%d\n", sizeof(&p[0] + 1));//4 char* 指向b
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
printf("%d\n", strlen(*p));//未定义行为
printf("%d\n", strlen(p[1]));//未定义行为
printf("%d\n", strlen(&p));//未定义行为.&p得到 char**
printf("%d\n", strlen(&p + 1));//未定义行为 同上
printf("%d\n", strlen(&p[0] + 1));//5
system("pause");
return 0;
}
sizeof求的是字符数组的长度;
strlen求的是字符串(一定要有\0)的长度,不算\0.
结构体
结构体就是一种自定制的类型.
本质上就是拿现有的类型组合一下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
enum Sex {
MALE,
FEMALE,
};
struct Student{
//结构体的成员/字段/属性
char name[10];
int age;
int score;
enum Sex sex;
};
int main(){
system("pause");
return 0;
}
创建 struct Student 这是为了在代码中表示"学生"这样的概念.
抽象,从它的反义词来理解;信息量越多他就越具体,信息量越少他就越抽象
写代码为了解决现实中的问题.需要用代码表示一些现实中的事物.根据我们的实际需要,提取一部分我们需要的信息,用代码表示出来就是抽象.
strcpy 字符串拷贝,把一个字符串复制一份,复制到另外一个数组中.
C语言中不能直接使用 = 给字符串赋值.
int main(){
//struce Student 是一个整体.构成了自定制的一种类型
// s 的类型就叫 struct Student,而不是Student.
Student s = {"zhnagsan", 18, 100, MALE};
//成员访问操作符,访问到结构体中的成员
strcpy(s.name,"李四");
printf("%s\n", s.name);
s.age = 20;
printf("%d\n", s.age);
system("pause");
return 0;
}
一个汉字占几个字节?
和操作系统/编译器,无关.
和字符编码方式相关.
使用一个更大的表格来表示汉字,每一个汉字和一个数字对应.
GBK:Windows 简体中文版默认编码,用两个字节表示一个汉字
UTF-8:Linux默认的编码方式,变长编码.对于汉字来说一般是三个字节.
成员访问:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum Sex {
MALE,
FEMALE,
};
struct Student{
//结构体的成员/字段/属性
char name[1024];
int age;
int score;
enum Sex sex;
};
typedef struct Student Student;
//不太推荐
//#define Student struct Student
int main(){
//struce Student 是一个整体.构成了自定制的一种类型
// s 的类型就叫 struct Student,而不是Student.
Student s = {"zhnagsan", 18, 100, MALE};
Student* p = &s;
printf("%s\n",s.name);
printf("%s\n",(*p).name);
// -> 操作等价于上面的先 * 再 .
printf("%s\n",p -> name);
system("pause");
return 0;
}
结构体传参:C语言中如果需要给结构体传参,可以无脑传指针.(开销小)
//结构体传参
void print1(struct Student s){
printf("%d\n",s.num);
}
//结构体地址传参
void print2(struct Student* ps){
printf("%d\n",ps->num);
}