星海's Blog

老头初学编程
漫谈C语言及如何学习C语言(转)
C初级知识(二)

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对应的无符号类型。

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter