1.................................................................................................................数值一律用补码:
正整数用原码表示,负整数用补码表示。
浮点数如果是负数,小数点之前用原码表示。
2.................................................................................................................常量(0,1,2,3)不能赋值给char数组,因此x[0]=0='\0'
F3349F17EE355BB87F1CA15568B41A07.png
3.................................................................................................................按执行频率排列 case 语句
把最常执行的情况放在前面,而把最不常执行的情况放在后面。最常执行的代码可能 也是调试的时候要单步执行的最多的代码。如果放在后面的话,找起来可能会比较困难,而 放在前面的话,可以很快的找到。
4.................................................................................................................break;break 关键字很重要,表示终止本层循环。现在这个例子只有一层循环,当代码执行到
break 时,循环便终止。
continue:如果把 break 换成 continue 会是什么样子呢?continue 表示终止本次(本轮)循环。当 代码执行到 continue 时,本轮循环终止,进入下一轮循环。
5.................................................................................................................
86345D41FDB3346DBDD6AA8A91020BFD.png6.................................................................................................................
半开半闭区间写法和闭区间写法虽然功能是相同,但相比之下,半开半闭区间写法写法更加 直观。
开区间指的是区间边界的两个值不包括在内.闭区间指的是区间边界的两个值包括在内.半开半闭区间指的是,开区间一边的边界值不包括在内,而闭区间一边的边界值包括在内.
7.................................................................................................................
不能在 for 循环体内修改循环变量,防止循环失控
8.................................................................................................................
把循环嵌套控制在 3 层以内。国外有研究数据表明,当循环嵌套超过 3 层,程序员对循环的理解能力会极大的降低。
如果你的循环嵌套超过 3 层,建议你重新设计循环或是将循环内的代码改写成一个字函数。
9.................................................................................................................
goto 关键字
goto 关键字
一般来说,编码的水平与 goto 语句使用的次数成反比。有的人主张慎用但不禁用 goto 语句,但我主张禁用。关于 goto 语句的更多讨论可以参看 Steve McConnell 的名著《Code Complete. Second Edition》。
10.................................................................................................................
我
典型的如内存操作函数 memcpy 和 memset 的函数原型分别为:void * memcpy(void *dest, const void *src, size_t len);void * memset ( void * buffer, int c, size_t num ); void 不能代表一个真实的变量。
11 ................................................................................................................
return 语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结束时 被自动销毁。
20494ADB-0E95-4BE8-BF8B-8A5D9F311C97.png 4FB093313E186F7E9A4EAAB29701AA74.png
堆和栈内存
我们都知道程序都是有自己的堆和栈内存的,我们使用的变量,常量一般都是放在栈当中,常量和全局变量一般放在全局栈中,而函数的局部变量都放置在函数的局部栈当中.当我们不适用堆内存而只是用栈内存处理函数调用间的数据时,要防止破坏函数的调用栈,如果破坏掉程序将报异常,有时候的异常还是很难定位的.
首先说,只要是动态分配了内存的指针,一定是在堆上,也就是使用了new、malloc等方式的指针;而指向临时变量地址的指针是在栈上。
*******************MRC return. copy. ******************
12.................................................................................................................
节省空间,避免不必要的内存分配,同时提高效率
const 编译器通常不为普通 const 只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。 例如:
define M 3
const int N=5; ......int i=N;int I=M;
int j=N; int J=M;
//宏常量//此时并未将 N 放入内存中
//此时为 N 分配内存,以后不再分配! //预编译期间进行宏替换,分配内存
//没有内存分配 //再进行宏替换,又一次分配内存!
const 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define 一样给出的是立即数,所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为 它是全局的只读变量,存放在静态区),而#define 定义的宏常量在内存中有若干个拷贝。 #define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值。 #define 宏没有类型,而 const 修饰的只读变量具有特定的类型。
// p 可变,p 指向的对象不可变 // p 可变,p 指向的对象不可变 // p 不可变,p 指向的对象可变
const int *p;int const *p;int *const p;const int *const p; //指针 p 和 p 指向的对象都不可变
13.................................................................................................................
extern
14…………………………………………………………………………………………………..
struct 关键字struct 是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用。
在网络协议、通信控制、嵌入式系统、驱动开发等地方,我们经常要传送的不是简单 的字节流(char 型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。
15…………………………………………………………………………………………………..柔性数组
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结 构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可 变的数组。sizeof 返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用 malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组 的预期大小。
16…………………………………………………………………………………………………..struct 与 class 的区别
在 C++里 struct 关键字与 class 关键字一般可以通用,只有一个很小的区别。struct 的成 员默认情况下属性是 public 的,而 class 成员却是 private 的。 truct 关键字与 class 关键字可以 通用,你也不要认为结构体内不能放函数了
17…………………………………………………………………………………………………..union 关键字如果一些数据 不可能在同一时间同时被用到,则可以使用 union。 union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置 空间,在 union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所 有的数据成员具有相同的起始地址 。
18………………………………………………………………………………………………….大小端模式对 union 类型数据的影响
大端模式和小端模式:
大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放
在高地址中。
小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放
在低地址中。
19.…………………………………………………………………………………………………enum 关键字
enum enum_type_name
{ENUM_CONST_1, ENUM_CONST_2, ... ENUM_CONST_n
} enum_variable_name;
20.贪婪法--- 贪心算法
//分别有1,5,10,50,100元,分别有5,2,2,3,5张纸币。问若要支付k元,则需要多少张纸币?
const int N = 5;
int Money[N]={5,2,2,3,5};
int Value[N]={1,5,10,50,100};
int min_fun(int a, int b)
{
int min;
return min=a<b?a:b;
}
int solve(int money){
int num = 0;
for (int i=N-1; i>0; i--) {
int middle = money/Value[i];
int c = min_fun(middle, Money[i]);
money = money-Value[i]*c;
num += c;
}
if (money > 0) {
return num;
}
return num;
}
int main(void)
{
printf("%d",solve(520));
return 0;
}
19.…………………………………………………………………………………………………#line 30 a.h
其中,文件名 a.h 可以省略不写。 这条指令可以改变当前的行号和文件名,例如上面的这条预处理指令就可以改变当前的行号 为 30,文件名是 a.h。初看起来似乎没有什么用,不过,他还是有点用的,那就是用在编译 器的编写中,我们知道编译器对 C 源码编译过程中会产生一些中间文件,通过这条指令, 可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析。
20.…………………………………………………………………………………………………为什么会有内存对齐?
21.…………………………………………………………………………………………………避免内存对齐?
1.…………………………………………………………………………………………………数组指针
-
a 作为右值,代表数组元素的首地址,而非数组的首地址。
a 作为右值时其意义与&a[0]是一样,代表的是数组首元素的首地址。 -
…………………………………………………………………………………………………很多初学者弄不清指针和数组到底有什么样的关系。我现在就告诉你:他们之间没有
任何关系!只是他们经常穿着相似的衣服来逗你玩罢了。
指针就是指针,指针变量在 32 位系统下,永远占 4 个 byte,其值为某一个内存的地址。 指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到。
数组就是数组,其大小与元素的类型和个数有关。定义数组时必须指定其元素的类型
和个数。数组可以存任何类型的数据,但不能存函数。
A),char *p = “abcdef”; B),char a[] = “123456”;
3………………………………………………………………………………………………….
int a[5]={1,2,3,4,5};int ptr=(int )(&a+1);
printf("%d,%d",(a+1),(ptr-1));
&a + 1: 取数组 a 的首地址,该地址的值加上 sizeof(a) 的值,即 &a + 5*sizeof(int),也 就是下一个数组的首地址,显然当前指针已经越过了数组的界限。
(int *)(&a+1): 则是把上一步计算出来的地址,强制转换为 int * 类型,赋值给 ptr。
*(a+1): a,&a 的值是一样的,但意思不一样,a 是数组首元素的首地址,也就是 a[0]的 首地址,&a 是数组的首地址,a+1 是数组下一元素的首地址,即 a[1]的首地址,&a+1 是下一 个数组的首地址。所以输出 2
*(ptr-1): 因为 ptr 是指向 a[5],并且 ptr 是 int * 类型,所以 *(ptr-1) 是指向 a[4] , 输出 5。
对指针进行加 1 操作,得到的是下一个元素的地址,而不是原有地址值直接加 1。所以,
一个类型为 T 的指针的移动,以 sizeof(T) 为移动单位。 因此,对上题来说,a 是一个一 维数组,数组中有 5 个元素; ptr 是一个 int 型的指针。
********* a 是数组首元素的首地址,也就是 a[0]的 首地址,&a 是数组的首地址,
1.定义分配的内存,而声明没有。 定义只能出现一次,而声明可以出现多次
4.…………………………………………………………………………………………………
A),int p1[10];
B),int (p2)[10];
指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身
决定。它是“储存指针的数组”的简称。
数组指针:首先它是一个指针,它指向一个数组。在 32 位系统下永远是占 4 个字节, 至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。
5.…………………………………………………………………………………………………
C 语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元 素首地址的指针。
同样的,函数的返回值也不能是一个数组, 而只能是指针。这里要明确的一个概念就是:函数本身是没有类型的,只有函数的返回值 才有类型。
6 .…………………………………………………………………………………………………
我们把上一节讨论的列子再改写一下:
void fun(char *p) {
char c = p[3];//或者是 char c = *(p+3); }
int main() {
char *p2 = fun(p2); return 0;
}
“abcdefg”;
这个函数调用,真的把 p2 本身传递到了 fun 函数内部吗?
我们知道 p2 是 main 函数内的一个局部变量,它只在 main 函数内部有效。(这里需要 澄清一个问题:main 函数内的变量不是全局变量,而是局部变量,只不过它的生命周期和
全局变量一样长而已。全局变量一定是定义在函数外部的。初学者往往弄错这点。)既然它 是局部变量,fun 函数肯定无法使用 p2 的真身。那函数调用怎么办?好办:对实参做一份 拷贝并传递给被调用的函数。即对 p2 做一份拷贝,假设其拷贝名为_p2。那传递到函数内 部的就是_p2 而并非 p2 本身。
网友评论