指针与一维数组
函数调用的本质是值传递
数组传递是弱化为指针
如果指针变量已指向数组中的一个元素,则p+1指向同一数组的下一个元素,执行p+1并不是将p的值(地址)加1,而是加上一个数组元素所占用的字节数。
#include <stdio.h>
int main() {
int a[3] = { 2,7,8 };
int* p;
int j;
p = a;//让指针变量p,指向数组的开头
j = *p++;//j=*p;p++ 后加加去掉 看优先级是否高于++ 高于则是*p整体
printf("a[0]=%d,j=%d,*p=%d\n", a[0], j, *p);
}
输出
2 2 7
#include <stdio.h>
int main() {
int a[3] = { 2,7,8 };
int* p;
int j;
p = a;//让指针变量p,指向数组的开头
//j = *p++;//j=*p;(*p)++ 任何时候后加加去掉 看优先级是否高于++ 高于则是*p整体
j = (*p)++;
printf("a[0]=%d,j=%d,*p=%d\n", a[0], j, *p);
}
输出
3 2 3
#include <stdio.h>
int main() {
int a[3] = { 2,7,8 };
int* p;
int j;
p = a;//让指针变量p,指向数组的开头
//j = *p++;//j=*p;p++ 后加加去掉 看优先级是否高于++ 高于则是*p整体
j = *p++;
printf("a[0]=%d,j=%d,*p=%d\n", a[0], j, *p); //2 2 7
j = p[0]++; //j = p[0];p[0]++
printf("a[0]=%d,j=%d,*p=%d\n", a[0], j, *p);//2 7 8
}
指针与一维数组及malloc动态申请空间
数组一开始定义好就确定下来了,C语言的数组长度固定是因为其定义的整型、浮点型、字符型变量、数组变量都在栈空间。而栈空间的大小在编译时是确定的。如果使用的空间大小不确定,那么就要使用堆空间
malloc函数。在执行#include <stdlib.h> void malloc(size_t size);时,需要给malloc传递的参数是一个整型变量,因为这里的size_t即int;返回值为 void 类型的指针,void* 类型的指针只能用来存储一个地址而不能进行偏移,因为malloc并不知道我们申请的空间用来存放什么类型的数据。所以确定要用来存储什么类型的数据后,都会将void*强制转换为对应的类型。
#include <stdio.h>
#include <stdlib.h>
//malloc可以帮我们实现动态数组
int main() {
int i; //申请多大的空间
scanf("%d", &i);
char* p;
p = (char*)malloc(i);//malloc申请空间的单位是字节
strcpy(p,"malloc success");
puts(p);
free(p);//释放空间
p = NULL;//如果不把p赋为null, p为野指针
return 0;
}
#include <stdio.h>
#include <stdlib.h>
char* print_stack() {
char c[13] = "I am a stack";
puts(c);
return c;
}
char* print_malloc() {
char* p = (char*)malloc(25);
strcpy(p, "I am print_malloc");
puts(p);
return p;
}
int main() {
char* p;
p = print_stack(); //栈空间会随着函数的执行结束而释放
puts(p); //???打印成功 不理解
p = print_malloc();//堆空间不会随子函数的结束而释放,必须自己free
puts(p);
return 0;
}
栈空间演示失败 和视频 不一样******
字符指针与字符数组的初始化
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* p = "hello"; // 把字符型常量"hello"的首地址赋给p
char c[10] = "hello"; //等价于strcpy(c,"hello")
c[0] = 'H';
//p[0] = 'H'; //不可以对常量区数据进行修改
//p = "world";
printf("c[0]=%c\n", c[0]);
printf("p[0]=%c\n", p[0]);
p = "world"; //将字符串world的地址赋给p
// c = "world"; //非法
puts(p);
return 0;
}
二级指针
#include <stdio.h>
void change(int** p, int* pj) {
*p = pj;
}
//要想在子函数中改变一个变量的值,必须把该变量的地址传进去
//要想在子函数中改变一个指针变量的值,必须把该指针变量的地址传进去。
int main() {
int i = 10;
int j = 5;
int* pi = &i;
int* pj = &j;
printf("i=%d,*pi=%d,*pj=%d\n", i, *pi, *pj);
change(&pi, pj);
printf("i=%d,*pi=%d,*pj=%d\n", i, *pi, *pj);
}
函数的嵌套调用
个一个C程序由一个主函数和若干其他函数构成。一个较大的程序可分为若干程序模块,每
个模块实现一个特定的功能。在高级语言中用子程序实现模块的功能,而子程序由函数来实现。
#include <stdio.h>
int i = 10; //全局变量,在函数外定义的变量叫全局变量
void print(int a) { //自定义print函数
printf("print i = %d\n", i);
}
int main() {
printf("main i = %d\n", i);
i = 5; //访问的就是全局变量 改了 数据区
print(i);
return 0;
}
// 10 5
#include <stdio.h>
int i = 10; //全局变量,在函数外定义的变量叫全局变量
void print(int a) { //自定义print函数 a=5
printf("print i = %d\n", i); //i 全局变量
}
int main() {
printf("main i = %d\n", i);
int i = 5; //main 里面定义了一个局部变量 栈空间
print(i);
return 0;
}
//10 10
递归调用
就是函数调用自己,有出口
#include <stdio.h>
int factorial(int n) {
if (n == 1) {
return 1;
}
else {
return factorial(n - 1) * n;
}
}
int main() {
int n =3,result;
if (n > 2) {
result = factorial(n);
printf("n的阶乘为%d\n", result);
}
}
结构体
#include <stdio.h>
#include <stdlib.h>
struct student {
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}; //结构体声明,注意最后一定要加分号
int main() {
struct student s = { 1001,"shabi",'m',24,98.0,"lianyungang" };
printf("%d %s %c %d %f %s\n", s.num, s.name, s.sex, s.age, s.score, s.addr);
struct student sarr[3];
for (int i = 0; i < 3; i++) {
scanf("%d%s %c%d%f%s", &sarr[i].num, sarr[i].name, &sarr[i].sex, &sarr[i].age, &sarr[i].score, &sarr[i].addr);
}
for (int i = 0; i < 3; i++) {
printf("%d %s %c %d %f %s\n",sarr[i].num,sarr[i].name,sarr[i].sex,sarr[i].age,sarr[i].score, sarr[i].addr);
}
return 0;
}
结构体指针
一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设置--个指针变量,用它指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素.
typedef的使用
可以使用typedef 声明新的类型名来代替已有的类型名。
#include <stdio.h>
#include <stdlib.h>
//结构体指针
typedef struct student {
int num;
char name[20];
char sex;
}stu,*pstu;
typedef int INTERGER;
int main() {
stu s = { 1001,"zzhaoguoyu",'m' };
pstu p;//stu* p1,那么p1也是一个结构体指针
INTERGER i = 10;
p = &s;
printf("i=%d,p->num=%d\n", i, (*p).num);
system("pause");
}
使用stu定义结构体变量和使用struct student 定义结构体变量是等价的;使用INTERGER定义变量i和使用int定义变量i是等价的;pstu等价于struct student *,所以p是结构体指针变量
C++的引用
#include <stdio.h>
//把&写到形参的位置是C++的语法,称为引用
void modify_num(int& b) {
++b;
}
int main() {
int a = 10;
modify_num(a);
printf("a=%d\n", a);
}
数据结构的三要素:逻辑结构、数据的运算、物理结构(存储结构)
逻辑结构
- 集合结构
- 线性结构
- 树形结构
- 图形结构
存储结构
- 顺序存储
- 链式存储
- 索引存储
- 散列存储
顺序存储可以实现随机存取,每个元素占用最少的空间。
只能使用整块的存储单元,会产生出较多的碎片
链式存储充分利用所有存储单元,不会出现碎片现象
需要额外的空间用来存放下一节点的指针,只能实现顺序存取
算法
程序 = 数据结构 + 算法
对特定问题求解步骤的描述
特性:有穷、确定、可行、输入、输出
时间复杂度
秒表,去记录算法的运行时间,为什么不用时间,同一个算法在不同的硬件机器上执行的时间是差别很大的
运行次数去表示时间复杂度,因为时间和运行次数是正相关的。
时间复杂度指算法中所有语句的频度(执行次数)之和。
T(n)=O(f(n))
其中,n是问题的规模;f(n)是问题规模n的某个函数。
表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同。
常见的时间复杂度:
O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2^n)<O(n!)
最高阶数越小,说明算法的时间性能越好。
思考:如果一个算法的执行次数为3n^3+5n,那么该算法的时间复杂度为多少?
时间复杂度是要忽略高阶项系数,和低阶项。T(n)=O(n^3)
线性表
描述的是线性表的逻辑结构,是独立于存储结构的!
动态分配并不是链式存储,同样还是顺序存储结构,物理结构没有变化,依然是随机存储,只是分配的空间大小可以在运行时决定。
标签:main,int,C语言,++,printf,include,指针 From: https://www.cnblogs.com/hekang520/p/17058139.html