C 提高第一天复习
内存四区,变量常量的本质,函数调用模型,栈开口方向,指针铁律1,指针是一种数据类型
C 提高学员标准:写一个标准的冒泡排序
选择法或者冒泡法排序
在一个函数内排序
通过函数调用的方式排序
数组做函数参数的技术盲点和推演
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i = 0;
int j = 0;
int tmp = 0;
int a[] = {3,66,54,32,11,22,99,2334,32};
for (i = 0; i < sizeof(a) / sizeof(int); i++)
{
printf("%d ",a[i]);
}
printf("\n", a[i]);
for (i = 0; i < sizeof(a) / sizeof(int); i++)
{
for (j = i+1; j < sizeof(a) / sizeof(int); j++)
{
if (a[i] > a[j])
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
for (i = 0; i < sizeof(a) / sizeof(int); i++)
{
printf("%d ", a[i]);
}
printf("\n", a[i]);
system("pause");
}
编译运行:
3 66 54 32 11 22 99 2334 32
3 11 22 32 32 54 66 99 2334
请按任意键继续. . .
冒泡程序,优化输出与排序 与 函数的数组参数问题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printfArray(int array[], int len)
{
int i;
for (i = 0; i < len; i++)
{
printf("%d ", array[i]);
}
printf("\n", array[i]);
}
//数组做函数的参数的退回问题,退回为一个指针
//结论:把数组内存的首地址和有效长度传给被调用的函数
//本质:函数中的数组形参,编译器会把它当成指针处理
void sortArray(int array[], int len)
{
int i, j, tmp;
for (i = 0; i <len; i++)
{
for (j = i + 1; j < len; j++)
{
if (array[i] > array[j])
{
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
}
int main()
{
int a[] = {3,66,54,32,11,22,99,2334,32};
int len = sizeof(a) / sizeof(int);
printfArray(a, len);
sortArray(a,len);
printfArray(a, len);
system("pause");
}
编译运行:
3 66 54 32 11 22 99 2334 32
3 11 22 32 32 54 66 99 2334
请按任意键继续. . .
数据类型概念:
“类型”是对数据的抽象
类型相同的数据有相同的表示形式、存储格式以及相关的操作
程序中使用的所有数据都必定属于某一种数据类型
基本数据类型:typedef 数组与地址
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct teacher1{
char name[64];
int age;
}Teacher1;
//使用typedef,以后定义就是这样了 Teacher2 t2;
typedef struct teacher2{
char name[64];
int age;
}Teacher2;
int main()
{
int b[10];
printf("b:%d , b+1:%d \n", b, b + 1);
printf("&b:%d, &b+1:%d \n", &b, &b + 1);
// b 代表数组首元素的地址
// &b代表整个数组的地址
// &b+1代表跨过整个数组地址
struct teacher1 t1;
Teacher1.age = 0;
Teacher2 t2;
typedef int u32;
printf("u32 =%d \n",sizeof(u32));
system("pause");
}
编译运行:
b:3603504 , b+1:3603508
&b:3603504, &b+1:3603544
u32 =4
请按任意键继续. . .
数据类型的本质思考
思考数据类型和内存有关系吗?
C/C++为什么会引入数据类型?
数据类型的本质
数据类型可理解为创建变量的模具(模子);是固定内存大小的别名。
数据类型的作用:编译器预算对象(变量)分配的内存空间大小
程序举例,如何求数据类型的大小 sizeof(int *)
请问:数据类型可以有别名吗?数据类型可以自定义吗?(typedef)
数据类型大小C程序:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10;
int b[10] ;
printf("int a:%d \n", sizeof(a));
printf("int a:%d \n", sizeof(int *));
printf("int b:%d \n", sizeof(b));
printf("int b:%d \n", sizeof(b[0]));
printf("int b:%d \n", sizeof(*b));
printf("hello.....\n");
return 0;
}
编译运行:
C:\Users\chunli>gcc main.c & a
int a:4
int a:4
int b:40
int b:4
int b:4
hello.....
常量的探讨:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * getstr1()
{
char *p = "1234";
return p;
}
char * getstr2()
{
char *p = "5678";
return p;
}
int main()
{
char *p1 = NULL;
char *p2 = NULL;
p1 = getstr1();
p2 = getstr2();
printf("%s,%s \n", p1, p2);
printf("%d,%d \n", p1, p2);
system("pause");
}
编译运行:
1234,5678
14309464,14309644
请按任意键继续. . .
改一改:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * getstr1()
{
char *p = "1234";
return p;
}
char * getstr2()
{
char *p = "1234";
return p;
}
int main()
{
char *p1 = NULL;
char *p2 = NULL;
p1 = getstr1();
p2 = getstr2();
printf("%s,%s \n", p1, p2);
printf("%d,%d \n", p1, p2);
system("pause");
}
编译运行:
1234,1234
2054232,2054232
请按任意键继续. .
堆栈变量,函数返回一个被析构的内存空间块
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//堆
char * getmem(int size)
{
char *p = NULL;
p = (char *)malloc(size);
return p;
}
//栈
//return 不是把内存块返回出来,而是把首地址返回了
char * getmem2()
{
char p[20];
strcpy(p, "haha2 \n");
return p; //【危险!】p即将释放,但是地址返回去来了。
}
int main()
{
char *p = NULL;
p = getmem(20);
strcpy(p, "haha1 \n");
printf("%s",p);
free(p);
p = NULL;
p = getmem2();//返回了一个被析构的数据块
printf("%s", p);//不应该这么做!
system("pause");
}
编译运行:
haha1
haha2
请按任意键继续. . .
栈的开口方向:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int a;
int b;
printf("&a = %d \n", &a);
printf("&b = %d \n", &b);
system("pause");
}
编译运行:
C:\Users\chunli>gcc -o main.exe main.c & main
&a = 2686652
&b = 2686648
请按任意键继续. . .
数组基地址永远都是在下面:
指针铁律1:指针是一种数据类型
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//*p 在等号的左边 修改内存
//*p 在等号的右边 读取内存
char * getstr()
{
int *tmp = "hello \n";// 常量区
return tmp;
}
int main()
{
int a;
char *p1 = 100;//分配4个字节
p1 = &a;
*p1 = 20; //*就像一把钥匙,找到这个地址,并修改它
printf("%d \n", sizeof(p1));
printf("%d \n", *p1);
int b = 0;
b = *p1;
printf("%d \n", b);
char p2 = (char *)malloc(100);
char p3 = (char *)malloc(100);
char *p4 = getstr();
// *(p4 + 2) = 'K'; 因为返回的是常量 ,不能修改
printf("%s",p4);
system("pause");
}
指针经典话语:
1,指针指向谁,就把谁的地址赋给指针;
2,指针变量 和 它指向的内存空间变量是两个不同的概念
3,理解指针的关键是内存,没有内存哪里来的指针
变量的本质是一个固定大小的数据块,变量名就是数据块的编号
内存的使用范围:
main函数可以在栈分配内存/堆分配内存/全局分配内存,可以给子函数使用
子函数在栈分配的内存不能给主函数使用,但是堆内存与全局变量是可以给main使用
编译器会为每个程序分配一个内存4区,主函数与子函数公用这个内存4区
建立正确程序运行内存布局图是学好C的关键!
指针铁律1:指针是一种数据类型
1)指针也是一种变量,占有内存空间,用来保存内存地址
2)*p 操作内存;
3)*就像一把钥匙,通过一个地址(&a),去修改a变量的标示的内存空间
4)不断的给指针赋值,相当于不停的改变指针的指向。
5) 指针是一种数据类型,是指它指向内存空间的数据类型
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。