1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
// malloc 需要stdlib.h 勿忘使用free()来释放内存,否则可能引起内存泄漏 #include <stdio.h> #include <stdlib.h> int main(int argc, char const *argv[]) { // 分配指定字节数的内存空间,返回void指针(内存的第一个字节的地址),可强转成任何类型的指针 // 分配失败返回空指针 // 申请30个double类型值的空间 double * ptd; ptd = (double *)malloc(30 * sizeof(double)); *ptd = 3.14; ptd[1] = 222.222; //输出3.14和222.22 printf("%.2f\n%.2f", *ptd, ptd[1]); return 0; } // malloc(字节数) free(malloc返回的指针) 需要stdlib.h #include <stdio.h> #include <stdlib.h> int main(int argc, char const *argv[]) { int *ptd; int max; int i = 0; puts("pls key a array size"); scanf("%d", &max); // 利用malloc可以创建动态长度的数组 ptd = (int *) malloc(max * sizeof(int)); // NULL空指针,表示分配内存失败 if (ptd == NULL) { puts("null point"); return 1; } puts("pls key the array values"); // scanf返回值 a.正整数(正确输入参数的个数) b.0(用户输入不匹配) c.EOF(stdio.h里面定义的常量(通常值为-1),表示输入流已经结束) while(i < max && scanf("%d", &ptd[i]) == 1) { ++i; } for (i = 0; i < max; ++i) { printf("%d\n", ptd[i]); } puts("done"); // 释放内存 free(ptd); return 0; } // calloc(num, B) #include <stdio.h> #include <stdlib.h> int main(int argc, char const * argv[]) { int * p; // 与malloc()类似,只是calloc()多了个参数,表示所需分配内存单元的数量 // calloc()还有个特性就是所有分配的内存单元默认为0(某些硬件系统,浮点值0不是用全部位为0来表示的) p = (int *) calloc(10, sizeof(int)); // calloc()也是用free()释放内存空间的 free(p); return 0; } // volatile限定词 易变的 #include <stdio.h> int main(int argc, char const *argv[]) { // 限定词volatile告诉编译器该变量除了可被程序改变外还可以被其他代理改变。 // 典型地,它被用于硬件地址和与其他并行运行的程序共享的数据。 // 如:一个地址可能保存着当前的时钟时间,另一种情况是一个地址被用来接收来自其他计算器的信息。 volatile int loc1; //loc1是一个易变的位置 volatile int * ploc; //ploc指向一个易变的位置 return 0; } // 可能受其他代理影响的变量建议使用volatile关键字 #include <stdio.h> int main(int argc, char const *argv[]) { // 一些聪明的(优化的)编译器可能注意到两次使用了x,而没有改变它的值 // 它将x临时存放在一个寄存器中,当val2需要x时,直接从寄存器中读取以节省时间(这个过程被称为缓存) // 通常,缓存是一个好的优化方式,但如果在两个语句中其他代理改变了x的话就不是这样了 // 如果你没有使用volatile关键字来限定一个可能变化的值,编译器会试着优化代码 val1 = x; /* ... 中间是一些不使用x的代码 ... */ val2 = x; // const和volatile可以同时声明,前后顺序无所谓 volatile const int nowTime; const volatile int * changePoint; return 0; } // restrict #include <stdio.h> int main(int argc, char const *argv[]) { //restrict关键字通过允许编译器优化某几种代码增强了计算支持 //它只可用于指针,并表明指针是访问一个数据对象的唯一且初始方式 // 这里,指针restar是由malloc()分配的内存的唯一且初始化的方式 // par指针既不是初始化也不是访问数组ar中数据的唯一方式 // 所以不可以把它限定为restrict int ar[10]; int * restrict restar = (int *) malloc (10 * sizeof(int)); int * par = ar; // 用了restrict关键字后,编译器可以试着优化代码 将restar[i]+=3和restar[i]+=5合并成restar[i]+=8 // 而没有使用restrict关键字,编译器就不会优化代码,因为可能会有其他标识符可以改变数据的值,如:ar[i] *= 2; int i; for (i = 0; i < 10; ++i) { par[i] +=5; restar[i] +=5; ar[i] *= 2; par[i] +=3; restar[i] +=3; } // C库中有2个如下函数(都是复制内存用的) // memcpy()从位置s2把n个字节复制到s1,要求两个位置之间不重叠,但memmove()没这个要求 // 所以 memcpy()的参数中使用了restrict关键字 void * memcpy(void * restrict s1, const void * restrict s2, size_t n); void * memmove(void * s1, const void * s2, size_t n); return 0; } // 旧关键字新位置 #include <stdio.h> int main(int argc, char const *argv[]) { void ofmouth(int * const a1, int * restrict a2, int n); //以前的风格 void ofmouth(int a1[const], int a2[restruct], int n); //C99允许 //使用static表明函数调用中,实际参数是一个指向数组首元素的指针 //该数组至少有20个元素,这样做的目的是 //1.告诉编译器可以自由地做一些有关优化的假定 //2.告诉用户仅使用满足static要求的参数 double stick(double ar[static 20]); return 0; } |