字符串与指针变量
/*
* 字符串与指针
*
* 定义字符串的3种方式
*/
char str1[] = {'1','2','3','\0'};
char str2[] = "123";
char *str3 = "123";
printf("%s\n",str1); // 123
printf("%s\n",str2); // 123
printf("%s\n",str3); // 123
// str3[1] = 'X';
// printf("%s\n",str3);
// printf("hello world");
/*
* 通过指针变量接收字符串和通过数组变量接受字符串有什么区别
* 1.通过数组变量接收字符串,这个变量存储在栈中
* 2.通过指针变量接受字符串,这个字符串存储在堆中
*
* 存储区域不同带来的影响
* 1.存储在栈中,变量值可以修改,常量池不能修改
* 如果修改,程序会在修改指针的地方卡住
* 下面的代码不会执行
* 有些编译器直接报错
* 2.通过数组变量接收字符串,哪怕字符串中的数据类型和内容相同,每次定义也会重新分配存储空间
* 通过指针变量接收字符串,只要字符串中的类型相同,就只有第1次定义会分配存储空间
*/
char str4[] = "ajax";
char str5[] = "ajax";
printf("%p\n",str4); // 000000000064FDEB
printf("%p\n",str5); // 000000000064FDE6
char *str6 = "java";
char *str7 = "java";
printf("%p\n",str6); // 0000000000404008
printf("%p\n",str7); // 0000000000404008
return 0;
/*
* _ _
* / / / _|__|_
* \_ / \_ | |
*/
字符串指针的注意点
/*
* 1.通过{}定义的字符串,不能直接赋值给指针变量
* 只有通过双引号定义的字符串,才能直接赋值给指针变量
* 2.存储在栈中的数据离开作用域就会释放,存储在常量区
* 只有程序结束才能释放
* 3.通过数组保存字符串,则这个字符串不能作为函数的返回值
* 通过指针保存字符串,则这个字符串可以作为函数的返回值
* 4.如果数组作为函数的参数,那么函数的形参最好写指针而不是数组
*/
char *res = test();
printf("%s\n",res); // null
return 0;
}
char *test() {
char str[] = {'1','2','3','\0'};
return str;
}
函数和指针概述
void test();
int main() {
/*
* 如何定义指针函数
* 1.将函数声明拷贝过来
* 2.在函数的返回值和函数名称中间加一颗星
* 3.修改函数的名称
* 4.利用()将星和函数名括起来
* 5.此时p可以指向没有返回值没有形参的函数
* 6.p可以代替函数名进行调用
*/
void (*p)();
p = test;
printf("%p\n",test); // 00000000004015AC
printf("%p\n",&test); // 00000000004015AC
printf("%p\n",p); // 00000000004015AC
}
void test() {
}
指针强化练习1
int minus(int a,int b);
int sum(int a,int b);
int calculate(int a,int b,int (*fn)(int a,int b));
int main() {
/*
* 需求:定义函数,接收2个参数
* 函数可以返回两数的和差
*/
// int (*fn)(int a,int b);
// fn = minus;
// int res = fn(20,10);
// printf("%i\n",res); // 10
//
// fn = sum;
// int res2 = fn(20,10);
// printf("%i\n",res2); // 30
int res = calculate(10,20,sum);
printf("%i\n",res); // 30
}
/**
* 计算函数
* @param a 参与运算的数1
* @param b 参与运算的数2
* @param fn 运算方法
* @return 运算结果
*/
int calculate(int a,int b,int (*fn)(int a,int b)) {
return fn(a,b);
}
int minus(int a,int b){
return a - b;
}
int sum(int a,int b){
return a + b;
}
结构体概述
/*
* 结构体概况
* 1.什么是结构体
* 结构体和数组很像
* 数组专门用来存储相同累心的数据
* 结构体专门用来存储不同类型的数据
* 2.如何定义一个结构体变量
* 定义结构体类型
* 定义结构体变量
* 3.如何定义结构体类型
* struct 结构体类型名称 {
* 数据类型 属性名称;
* 数据类型 属性名称;
* };
* 4.如何使用结构体变量
* 结构体变量名称.结构体属性名称
*/
// 1.定义结构体类型
struct Person {
char* name;
int age;
};
// 2.定义结构体变量
struct Person p1;
/*
* 此时结构体变量能够存储
* char* int类型
*/
p1.age = 20;
p1.name = "Jack";
printf("%s\n",p1.name); // Jack
printf("%i\n",p1.age); // 20
结构体定义的多种格式
/*
* 结构体变量定义的多种格式
* 1.结构体类型和结构体变量分开定义
* (省略代码)
* 2.结构体类型定义同时定义结构体变量
* struct material {
* char* price;
* char* type;
* } material1;
* 3.省略结构体类型名称
* struct {
* char* price;
* char* type;
* } material2;
*
* 三种结构体定义的区别
* 1.主要1,2种方式和第3种方式的区别
* 2.第3种只能用1次,第1种可以复用
*/
/*
* 结构体变量的初始化方式
* 1.定义同时初始化
* 初始化的值必须和数据类型中定义的顺序一致
* 结构体变量和数组一样,也支持指定数据初始化
* 2.之前学数组的时候,不支持先定义再一次性初始化
* 结构体可以进行强制类型转换,但在企业开发中不推荐使用
*/
struct Material {
char* type;
float price;
};
struct Material material = {"food",12.0};
struct Material material1 = {.price = 16.0,.type = "digital"};
结构体的存储细节
struct Demo {
int num;
int value;
};
struct Demo d;
d.num = 1;
d.value = 3;