2018-01-15
0.计算机的思考方式:枚举,小范围内的枚举,二分法。
1.double的scanf("%lf",&...) ,print(f%,...)是没有问题的;
2.count++ 是 count原来的值;
3.scanf("%d",&x)
printf("%x",x) 此时的 %x 表示16进制,且字符只能是x字符;
4.什么是好的代码? 答:足够傻的代码。
5.所谓的else if是当年被屏幕宽度限制而所做的更改;“单一出口”
6.尊重warning,力争解决每一个warning。
7.if()中条件:零或非零。即:bool条件中只有零或非零。(非零表示正确)
8.风格三观。。。。。。每个企业都有自己的风格,服从企业风格。
9.计算机描述的步骤,而不是关系。
10.do while...语句是考虑了特殊情况,如:变量等于零。
11.for(int i = 2; i <= x; i++) //只有c99的编译器才支持for循环中的变量声明定义;
12.for(; i <= x; ){ i++;} 等同于 while(条件){}
//******************** 第六周 数据类型 *******************************
13.对于-a<10进制数>,其补码就是0-a,实际是2^n - a,n是这种类型的位数(溢出的零)。
14.unsigned(纯二进制的移位) ,255U / 255u
15.非unsigned的负一,就是unsigned最大值;例如:printf("int的最大值:%u 最小值:%d", -1 , -1);
16.整数的运算是准确的,浮点不一定准确。例如:
① f1==f2可能失败;但,当fabs(f1-f2)<f的精度时,f1==f2;
② 浮点也不能作为switch-case的条件跳转,只因它不够准确。
17.优先级:!> && > || ,!是单目运算符。例:!age<20 永远为真。
18.代码复制是程序质量不良的表现。例:维护不便;
19.无函数体(函数原型)就是声明<同时,声明‘可以’不需要写明参数名>,有,就是定义。(Ps:Java中不需要声明)
20.数组中的个数是定值,c99除外,它可以是变量。 Java中不可以。
21.我的编译器不是c99,int arr[10] = {[1]= 1,2, [5]=3}; //c中的数组的初始化 .
22.有没有读过7、80年代的计算机教科书,是看你有没有在数组定义时多留出一个逗号(‘,’),
23.计算机存储变量地址是按stack自顶向下(C语言的内存模型),即:由大到小;→
又:printf("%p %p %p", &a, a, &a[0])数组a[]得到:&a == &a[0]( 当,求sizeof所占字节时,!= a),从而推出:数组数据存储是按倒序存储。即:arr[i-1]、arr[i-2]...arr[0]。
24.i==*p, &i==p==&*p; 分别对其%d和%p输出,一共可以得到四组数据;
①32位:后者的%d和%p一样,
②邻地址单位差一个int;
!!!③与变量i不同的是:*p在左边时他是:左值,表达式计算的结果;原因:*是单目运算符,用于取值。类似的还有数组中的[];
25.金矿,传送门,&传送门==地图
26.数组变量和指针的关系
老师说数组变量可以被看作是const的指针变量,到底是“可以被看作”,还是“就是”指针呢?
用程序证据(而不是搜索教科书)来说明你的观点。
(提示:如果对const指针的所有的操作都可以对数组变量做,而且结果一致,就说明数组变量就是指针;如果有某个操作不能做,或者结果不一致,就说明不是指针)
①初始化:数组初始化:实际值; const指针:地址;
②sizeof:前者:是计算整个数组长度; 后者:一个指针大小(它的大小取决系统位数);
/*
int a[] = {1,2,3,};
int const* p = a; // // p = a; × 因为const必须要初始化;
int const * j;
printf("%d\n", sizeof(int)); //判断数据类型
printf("%d\n", sizeof(p+1)); //判断数据类型
printf("%d\n", sizeof(&a+2)); //判断数据类型
printf("%d\n", sizeof(a)); //数组长度
printf("%d\n", sizeof(&a[0])); //**数据类型
printf("%p\n", a);
printf("%p\n", a+1);
printf("%p\n", &a); a指的是一个数组元素的地址,就相当于&a[0],而&a是指整个数组的地址
printf("%p\n", &a+1); //两者地址差==整个数组长度
从而得出一个性质:在f(int arr[])中只需一个arr指针就可计算出该数组的长度;例:利用&a+1 - &a = 整个数组长度;
但是:
f(&a); // 不能把整个数组的地址都传过去; (int*[sizeof(arr)] not convert to int*)
printf("%p\n", &p);
printf("%p\n", &p+1); //两者地址差为:2
printf("%p\n", a);
printf("%p\n", &a[0]);
*/
27.0~24 32
25~40 48
41~56 64 推出:它以16的倍数递增;又:32-24=8,得:指针存储变量需8个位;
28.用指针还是数组表示字符串?
(1)构造字符串用数组;
(2)处理字符串用指针;
①数组:这个字符串就在这里:
本地变量内存会自动回收;
②指针:不知道字符串在哪儿;
作为参数;
动态内存分配;
29.结构与数组:
① 数组是结构的特殊情况
② 我觉得结构更倾向于自然的抽象,类似于面相对象的类,数组就规矩多了,
③ 结构变量名是普通的变量名,而数组名是指针常量;
④ 数组是相同类型的数据组成的在内存上连续分布的, 而结构体内数据类型不一定相同,
⑤ 这两者共同实现了对数据的集成,模块化,结构化
30.#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
;//声明预留
struct test fun(struct test fun1);
void printfmystruct(const char * p, const struct test * structname);
;//结构预留
struct test{
int arr[10];
};
//突发奇想:数组的值能否利用结构进出函数体,能否整体赋值
//已知不能直接用数组名将数组的值传递进函数体,现试验利用结构包装数组能否实现数组值的传递,也不能进行数组的整体赋值
//试验成功:数组的值能利用结构包装在函数中正确赋值,其中数组也能够整体赋值
int main()
{
struct test main1 = {{0,1,2,3,4,5,6,7,8,9}}, main2;
printfmystruct("main1", &main1);
//包含数组的结构体函数间赋值传递
main2 = fun(main1);
printfmystruct("main2", &main2);
return 0;
}
/*
功能:测试函数能否成功接收和返回结构体中的数组值,数组利用结构体进行整体赋值
说明:若10个数据完全正确则可信度很大,地址可判断内存是否重复
输入:结构体test
输出:结构体test
*/
struct test fun(struct test fun1)
{
struct test fun2;
printfmystruct("fun1", &fun1);
//包含数组的结构体直接赋值传递
fun2 = fun1;
printfmystruct("fun2", &fun2);
return fun2;
}
/*
功能:输出自定义结构体名称地址内容
说明:无
输入:指向字符串的指针,指向结构的指针
输出:空
*/
void printfmystruct(const char * p, const struct test * structname)
{
int i;
printf("%s:\t%p:\n", p, structname);
for (i = 0; i < 10; i++) {
printf("%4d", structname->arr[i]);
}
printf("\n");
return;
}
/*
功能:
说明:
输入:
输出:
*/
/*
void fun(void)
{
return;
}
*/
31.内存对齐,以结构体中某个类型占位最大的字节数作为单位,分别分配给各类型(分配原则:只多不少);
/*
测试用例:
rule 1:char double, char int
rule 2:int int double,int double
rule 3:①char1 char2 ... char5 int double;
char1~4,每个占一个字节,char5‘占’4个字节(其中有三个字节空着);
②“依次” int int double, int double char
rule 4:由以上三条组成;
rule 0:结构体变量地址 = = 结构体内第一个数据类型变量的地址;
rule 1,得到结构体里面最长的一个变量作为参考长度L。
rule 2,一个变量的实际占的空间和后面紧跟变量比较,取较长size做基本单位进行填充。
rule 3 , 如果几个变量“依次”累加的值超过‘下’一个变量类型字节数,则最后一个变量重起一行,分配 ‘下’一个变量类型字节数 大小的空间。
推论:结构体的总大小为结构体最宽基本类型成员大小的整数倍,
问题:
结构体内部数据类型,地址不一定连续;char1 char2 ... char5 int double;
char1~4,每个占一个字节,char5‘占’4个字节(其中有三个字节空着);
问题:这些空着的字节地址有内容么,或者说可以使用吗?
rule 4,各结构体间的地址间隙 = =‘下’一个结构体体内的最后一个数据类型sizeof*2;(暂不考虑编译器等其它因素影响);
*/
#include <stdio.h>
int main(void)
{
int i = 1;
struct date{
// int month;
int day;
double hour;
// char M;
}d1;
struct date2{
// int month;
// int day;
double hour;
char M;
}d2;
d1 = {
24,15.44
};
int* p;
// printf("%p\n", &d1.month);
printf("%p\n", &d1.day);
printf("%p\n", &d1.hour);
// printf("%p\n", &d1.M);
printf("%p\n",&d1);
printf("%d %d %d\n", sizeof(d1),sizeof(d2),sizeof(d1)-sizeof(d2));
printf("%p\n",&d2);
d2 = {
16.28,'P'
};
// printf("%p\n", &d2.month);
// printf("%p\n", &d2.day);
printf("%p\n", &d2.hour);
printf("%p\n", &d2.M);
return 0;
}
- typedef + 被更名量 + 应更名量;
- 被更名量:可以是一个或多个;
-
- ①typedef int length; ②typedef sturct Adate {} Date;
-
- 应更名量:一般为一个;
-
- ①typedef int length; ②typedef sturct Adate {} Date;
-
- 被更名量:可以是一个或多个;
- Typedef union Ch { int i; char [4]; } CHI;
所有成员变量所占空间只有一份,它们都公用这一份空间;
空间大小:sizeof(union ...) = Max{ sizeof(每个成员类型) };
- 全局变量的赋值必须是确定的值或常量(带const的变量 );
36.***** 局部变量static后,函数执行一次后,其值不随函数的消亡而消失,即:值被保留下来了;换句话,被重新初始化(其实没有,值始终存在);
void f2() {
Static int b = 0; //局部变量初始化;
b++;
Printf(“%d\t” , b);
}
int main(void) {
f2();
f2();
f2();
}
输出:1 2 3
37.由静态本地变量地址所在地,比较得出:其就是全局变量;
- 返回本地变量地址是危险的;
- 业主已经把房子租给别人了,你还留着那把钥匙干嘛。
- 基本宏定义
- _LIEN_ 行号
- _FIEL_ 文件名(从根路径起)
- _DATE_ 日期
- _TIME_ 时间
- 全局变量加上static,表示该变量只能在所在编译单元中使用(主要目的:在别人已经 使用.h后,依然不能使用该标记的static函数。static关键字类似Java中private);
函数加上static ,表示该函数只能在所在编译单元使用(同上);
②变量的声明;extern int i ;放在对应的.h下;
- 标准头文件结构:防止目标头文件被重复定义;部分编译器支持:#program once
- #ifndef _LIST_HEAD_
- #define _LIST_HEAD_
- ...
- #endif
42.格式化输出的转变;
sprintf(formata , "%%%ds" , &num); //若 num = 19;
//则,format == %19s
43.