C最初级知识
星海
posted @ 2010年12月13日 07:40
in C学习
, 1452 阅读
#include <stdio.h> int main(void) { int a, b, c; b = 5; c = 5; a = ++b + c--; //相当于顺序执行 b=b+1,a=b+c,c=c-1 printf("%d,%d,%d\n", a, b, c); a = b-- - c; //相当于顺序执行 a=b-c,b=b-1 printf("%d,%d,%d\n", a, b, c); a = -b++ + c; //相当于执行a=-b+c,b=b+1 printf("%d,%d,%d\n", a, b, c); a-=a-5; printf("%d\n",a); return 0; }
/* 给一个正整数, * 1,求出这是几位数 * 2,逆序输出它的每一位数字 * 3,!!通过逆序输出的每一位数字,重新合成这个正整形数据(不允许用reverse,atoi等函数 以及 数组 )*/ #include <stdio.h> #include <math.h> int main(void) { int a, i, temp, count = 1; //count记录位数 printf("input a int number : "); scanf("%d", &a); //a为输入的数字 temp = a; while (a / 10 != 0) { ++count; a = a / 10; } printf("这个数字有%d位数\n", count); a = temp; temp = 0; for (i = 0; i < count; ++i, a = a / 10) { printf("%d ", a % 10); temp += a % 10 * pow(10, i); //这里我借助了pow函数,有没有更简洁,不借助其他函数的办法呢? } printf("\n"); printf("这个数字是%d\n", temp); return 0; }
minute + 1 = hour; 等号左边的表达式要求表示一个存储位置而不是一个值,这是等号运算符和+ - * /运算符的又一个 显著不同。有的表达式既可以表示一个存储位置也可以表示一个值,而有的表达式只能表示值,不 能表示存储位置,例如minute + 1这个表达式就不能表示存储位置,放在等号左边是语义错误。表 达式所表示的存储位置称为左值(lvalue)(允许放在等号左边),而以前我们所说的表达式的值 也称为右值(rvalue)(只能放在等号右边)。上面的话换一种说法就是:有的表达式既可以做左 值也可以做右值,而有的表达式只能做右值。目前我们学过的表达式中只有变量可以做左值,可以 做左值的表达式还有几种,以后会讲到 如果定义三个变量int a, b, c;,表达式a = b = c是合法的,先求b = c的值,再把这个值赋给a,而表达式(a = b) = c是不合法的,先求(a = b) 的值没问题,但(a = b) 这个表达式不能再做左值了,因此放在= c的等号左边是错的。 在C语言中整数除法取的既不是Floor也不是Ceiling,无论操作数是正是负总是把小数部分截掉,在 数轴上向零的方向取整(Truncate toward Zero) 局部变量可以用类型相符的任意表达式来初始化,而全局变量只能用常量表达式 (Constant Expression)初始化。 如果全局变量在定义时不初始化则初始值是0,如果局部变量在定义时不初始化则初始值是不确定的。所以,局部变量在使用之前一定要先赋值,如果基于一个不确定的值做后续计算肯定会引入Bug。 (a/b)*b+a%b的值总是等于a A<B<C,不同于数学中的 a<b and b<c,而是等同于 a<b,为true或false,即1,0 ,然后判断1或0是否<c 以下哪一个if判断条件是多余的可以去掉?这里所谓的“多余”是指,某种情况下如果本来应该打印Test OK! ,去掉这个多余条件后仍然打印Test OK! ,如果本来应该打印Test failed!,去掉这个多余条件后仍然打印Test failed!。 if (x<3 && y>3) printf("Test OK!\n"); else if (x>=3 && y>=3) printf("Test OK!\n"); else if (z>3 && x>=3) printf("Test OK!\n"); else if (z<=3 && y>=3) printf("Test OK!\n"); else printf("Test failed!\n");
这个文件用typedef工具创建了新的类型名字。 比如:uint32_t作为一个具有某种特征的标准类型的同义词或别名。在某系统中这个标准类型可能是unsigned int,另一个系统可能是unsigned long.编译器会提供所在系统相一致的头文件。这个新的名称叫做“确切长度类型”。 使用“确切长度类型”的一个潜在问题是某些系统可能不支持一些选择,例如int8_t类型。C99标准定义了第二组名字结合。这些名字保证所表示的类型至少大于指定长度的最小类型。被称为“最小长度类型”。例如 int_least8_t,他在某些机器的实现也许是16位整数。 “最快最小长度类型” int_fast8_t。 “最大可能整数类型” intmax_t uintmax_t C99为表示浮点常量新添加了一种十六进制格式。最后是2的指数,而不是10 0xa.1fp10 a是10, 1f为十六进制小数,转2进制为1/16+15/256. p10表示2的十次方。结果为 (10+1/16+15/256)*2^10
#include <stdio.h> /* 参数传递机制 */ int main(void) { float n1 = 3.0; double n2 = 3.0; long n3 = 2000000000; long n4 = 1234567890; long n3_2 = 78888888; printf("%ld %ld %ld %ld %ld\n", n1, n2, n3, n4, n3_2); /* 该调用告诉计算机把变量n1...n4的值传给计算机。计算机把他们放知道被称为堆栈(stack)的一块内存区域中来实现。计算机根据变量的类型而非转换说明符把这些值放到堆栈中。所以,n1 在堆栈中占用8B(float被转换为double),n2 8B,n3/n4 4B。 * 然后控制转移到printf()函数。它在读取时,根据转换说明符号读取。%ld说明pf()读取4个字节。所以返回结果如下 * 0 1074266112 0 1074266112 * 如果我们再声明一个long int数值,读取的应该就是n3的值了。 */ return 0; }
#include <stdio.h> void show_array(double ar[], int n) { int i; for (i = 0; i < n; i++) printf("%8.3f", ar[i]); putchar('\n'); } int main(void) { double rates[5] = { 88.99, 100.12, 59.45, 183.11, 340.5 }; const double *pd = rates; /* 指向常量的指针不能用于修改数值, 这一行把pd声明为指向 const double的指针 */ double *const pc = rates; /* 指针不会指向别处,不可更改 */ //不允许*pd = 29.89; // pd[2] = 222.22; rates[0] = 99.99; pd++; /* 让pd指向rates[1],这是允许的 */ const double locked[5] = { 88.99, 100.12, 59.45, 183.11, 340.5 }; double *pnc; //只有非常量的地址才可以赋给普通指针 //非法: pnc = locked; //将常量数组作为非常量数组参数会警告或出错 show_array(locked, 5); return 0; }
#include <stdio.h> int main(void) { int a[5] = { 5, 2, 3, 1, 4 }; int *p1; const int *p2; const int **pp2; p2 = a; p1 = p2; /* 非法,把const指针赋值给非const指针 */ p2 = p1; /* 合法,把非const指针赋值给const指针 */ pp2 = &p1; /* 非法,把非const指针赋值给const指针 */ return 0; }
括号成员第一; //括号运算符[]() 成员运算符. -> 全体单目第二; //所有的单目运算符比如++ -- +(正) -(负) 指针运算*& 乘除余三,加减四; //这个"余"是指取余运算即% 移位五,关系六; //移位运算符:<< >> ,关系:> < >= <= 等 等于(与)不等排第七; //即== != 位与异或和位或; //这几个都是位运算: 位与(&)异或(^)位或(|) "三分天下"八九十; 逻辑或跟与; //逻辑运算符| 和 && 十二和十一; //注意顺序:优先级(||) 底于 优先级(&&) 条件高于赋值, //三目运算符优先级排到 13 位只比赋值运算符和","高//需要注意的是赋值运算符很多! 逗号运算级最低! //逗号运算符优先级最低
/*----------------------------------------------------------------------------- * typedef建立的一系列相关类型 *-----------------------------------------------------------------------------*/ typedef int arr5[5]; typedef arr5 *p_arr5; typedef p_arr5 arrp10[10]; arr5 togs; /* togs是具有5个元素的int数组 */ p_arr5 p2; /* p2是一个指针,指向具有5个元素的int数组 */ arrp10 ap; /* ap是具有10个元素的指针数组,每个指针指向具有5个元素的int数组 */
Initializer中的数据依次赋给结构体的各成员。如果Initializer中的数据比结构体的成员多,编译器会报错,但如果只是末尾多个逗号则不算错。如果Initializer中的数据比结构体的成员少,未指定的成员将用0来初始化,就像未初始化的全局变量一样。 z1必须是局部变量才能用另一个变量x的值来初始化它的成员,如果是全局变量就只能用常量表达式来初始化。这也是C99的新特性,C89只允许在{}中使用常量表达式来初始化,无论是初始化全局变量还是局部变量。
a,如果两边都是有符号数或无符号数,那么较低Rank的类型转换成较高Rank的类型 b,如果一边是符号数另一边是有符号数。 如果无符号数Rank不低于有符号数的Rank,则把有符号数转换为另一边的无符号类型。 如果无符号数Rank低于有符号数的Rank。此时分两种情况。 (1),如果这个有符号数类型能够覆盖这个无符号数类型的取值范围,则把无符号数转成另一边的有符号类型。 (2),否则把两边都转换成有符号数Rank对应的无符号类型。