<一>继续Hello World
深入了解C语言的注释&#xff0c;注释可以跨行&#xff0c;也可以穿插在程序中。注释的定界符/*和*/&#xff0c;注释需要注意两点&#xff1a;注释不能够嵌套使用&#xff0c;如&#xff1a;/*test1 /* test2 */ test3 */,编译器解释时&#xff0c;只把/*test1 /*test 2*/看成注释&#xff0c;后面的test3 */无法解释错误。2.C语言中也可以用//来注释内容&#xff0c;两个/斜线&#xff08;Slash&#xff09;表示从这里直到该行末尾的所有字符都属于注释&#xff0c;这种注释不能跨行&#xff0c;也不能穿插在一行代码中间。这是从C&#43;&#43;借鉴的语法。
#include
/*
 * comment1
 * main: generate some simple output
 */
//这里跨四行在注释里面的“*”号&#xff0c;没有特殊含义&#xff0c;为了整体可观赏性&#xff0c;这不是语法而是大家遵守的C代码风格&#xff08;Coding Style&#xff09;之一。
int main(void)
{
 printf(/* comment2 这里可以穿插程序注释*/"Hello, world.\n"); /* comment3 可以在程序语句末尾穿插注释*/
 return 0;
}
解释C标准规定的转义字符具体含义
\&#39; 单引号&#39;&#xff08;Single Quote或Apostrophe&#xff09;
\" 双引号"
\? 问号?&#xff08;Question Mark&#xff09;
\\ 反斜线\&#xff08;Backslash&#xff09;
\a 响铃&#xff08;Alert或Bell&#xff09;
\b 退格&#xff08;Backspace&#xff09;
\f 分页符&#xff08;Form Feed&#xff09;
\n 换行&#xff08;Line Feed&#xff09;
\r 回车&#xff08;Carriage Return&#xff09;
\t 水平制表符&#xff08;Horizontal Tab&#xff09;
\v 垂直制表符&#xff08;Vertical Tab&#xff09;
"Hello World.\n"这里双引号&#xff08;Double Quote&#xff09;引起来的一串字符称为字符串字面值&#xff08;String Literal&#xff09;,或称为字符串。printf打印出来的只是里面的一串字符Hello World,因此双引号是字符串字面值的界定符。而\n没有输出。因为\n这两个字符合为一体表示换行&#xff08;Line Feed&#xff09;&#xff0c;并不是字面意思。
如果在字符串字面值中要表示单引号和问号&#xff0c;既可以使用转义序列\&#39;和\?&#xff0c;也可以直接用字符&#39;和?&#xff0c;而要表示\或"则必须使用转义序列&#xff0c;因为\字符表示转义而不表示它的字面含义&#xff0c;"表示字符串的界定符而不表示它的字面含义。可见转义序列有两个作用&#xff1a;一是把普通字符转义成特殊字符&#xff0c;例如把字母n转义成换行符&#xff1b;二是把特殊字符转义成普通字符&#xff0c;例如\和"是特殊字符&#xff0c;转义后取它的字面值。C语言规定了几个控制字符&#xff0c;不能用键盘直接输入&#xff0c;因此采用\加字母的转义序列表示。字符串字面值中的空格也算一个字符&#xff0c;也会出现在输出结果中&#xff0c;而程序中别处的空格和Tab多一个少一个往往是无关紧要的&#xff0c;不会对编译的结果产生任何影响。
#include
int        main         (void)
//程序其他空格及Tab对程序无影响&#xff0c;但不是好的编程习惯
{
 printf("Hello,      world.    0\n");
 //字符串字面值一个空格算一个字符。Hello,与World.间的空格及world.与0间的空格&#xff0c;照原样输出。
 return 0;
}
上面的程序也可以写成&#xff1a;
#include
int main(void){printf("Hello,      world.    0\n");return 0;}
//不缩进不会影响程序的结果&#xff0c;一个头文件占一行&#xff0c;main后面多几个空格也没影响&#xff0c;但是int和main之间至少要有一个空格分隔开

<二>常量
常量&#xff08;Constant&#xff09;是程序中最基本的元素&#xff0c;有字符&#xff08;Character&#xff09;常量、整数&#xff08;Integer&#xff09;常量、浮点数&#xff08;Floating Point&#xff09;常量和 枚举常量
#include
int main(void)
{
        printf("character:%c\ncharater: %c\ncharater: %c\ncharater: %c\ncharater: %c\ncharater: %c\ncharater: %c\ncharater: %c\ninteger: %d\nfloating point: %f\n",&#39;}&#39;,&#39;"&#39;,&#39;?&#39;,&#39;\n&#39;,&#39;\&#39;&#39;,&#39;?&#39;,&#39;\&#39;&#39;,&#39;\\&#39;,34,3.14);
        return 0;
}
字符常量要用单引号括起来&#xff0c;如&#xff1a;&#39;{&#39;,注意但引号只能括一个字符而不能像双引号那样括一串字符&#xff0c;字符常量也可以是一个转义序列&#xff0c;如:&#39;\n&#39;.这时虽然单引号括了两个字符&#xff0c;但实际上只表示一个字符。和字符串字面值中使用转义序列有一点区别&#xff0c;如果在字符常量中要表示双引号"和问号&#xff1f;&#xff0c;既可以使用转义序列\"和\?&#xff0c;也可以直接用字符"和&#xff1f;&#xff0c;而表示&#39;和\则必须使用转义序列。
printf中的第一个字符串称为格式化字符串&#xff08;Format String&#xff09;&#xff0c;它规定了后面几个常量以何种格式插入到这个字符串中&#xff0c;在格式化字符串中%号&#xff08;Percent Sign&#xff09;后面加上字母c、d、f分别表示字符型、整型和浮点型的转换说明&#xff08;Conversion Specification&#xff09;&#xff0c;转换说明只在格式化字符串中占个位置&#xff0c;并不出现在最终的打印结果中&#xff0c;这种用法通常叫做占位符&#xff08;Placeholder&#xff09;。这也是一种字面意思与真实意思不同的情况&#xff0c;但是转换说明和转义序列又有区别&#xff1a;转义序列是编译时处理的&#xff0c;而转换说明是在运行时调用printf函数处理的。源文件中的字符串字面值是"character: %c\ninteger: %d\nfloating point: %f\n"&#xff0c;\n占两个字符&#xff0c;而编译之后保存在可执行文件中的字符串是character&#xff1a; %c换行integer: %d换行floating point: %f换行&#xff0c;\n已经被替换成一个换行符&#xff0c;而%c不变&#xff0c;然后在运行时这个字符串被传给printf&#xff0c;printf再把其中的%c、%d、%f解释成转换说明,双引号括起来的是字符串&#xff0c;表示一串字符。单引号括起来的是字符&#xff0c;表示一个字符&#xff0c;除特殊的外。什么都不加的是一个整数。分别表示&#xff1a;"66666"、&#39;6&#39;、6
<三>变量
变量是计算机存储器中的一块命名空间&#xff0c;可以在里面存储一个值&#xff08;Value&#xff09;,存储的值是随时变的&#xff0c;比如这次存个字符&#39;3&#39;下次存个字符&#39;4&#39;&#xff0c;正因为变量的值随时变所以才叫变量。常量有不同的类型&#xff0c;因此变量也有不同的类型&#xff0c;变量的类型也决定了它所占的存储空间的大小。例如&#xff1a;定义四个变量&#xff1a;a、b、c和d,a是字符占1个字节、b是整型2个字节、c和d是浮点型&#xff0c;c是单精度浮点型占4个字节&#xff0c;d是双精度浮点型占8个字节。变量的存储单位是字节&#xff08;Byte&#xff09;,在C语言中char型变量占一个字节&#xff0c;其它类型的变量占多少个字节在不同平台上有不同的规定
char a;
int b;
float c;
double d;
C语言中声明&#xff08;Declaration&#xff09;有变量声明、函数声明和类型声明三种。
变量的声明及定义&#xff0c;给变量命名&#xff1a;变量命名建议用专业化术语&#xff0c;如&#xff1a;hour表示小时变量&#xff0c;minute表示分的变量。给变量命名的规则&#xff1a;C语言规定必须以字母或下划线_(Underscore)开头&#xff0c;后面可以跟若干个字母、数字、下划线&#xff0c;但不能有其它字符。例如合法的变量名&#xff1a;Ac_bb、_12_、a_1_b123 ,不合法的变量名&#xff1a;$c、4_c、ab?_,a>b,C.C 等&#xff0c;其实这个规则不仅适用于变量名&#xff0c;也适用于所有可以由程序员起名的语法元素。同类型变量可以一起定义&#xff0c;如&#xff1a;int hour,minute;
注意&#xff1a;一般来说应避免使用以下划线开头的标识符&#xff0c;以下划线开头的标识符只要不和C语言关键字冲突的都是合法的&#xff0c;但是往往被编译器用作一些功能扩展&#xff0c;C标准库也定义了很多以下划线开头的标识符&#xff0c;所以除非你对编译器和C标准库特别清楚&#xff0c;一般应避免使用这种标识符&#xff0c;以免造成命名冲突。
<四>赋值
定义变量&#xff0c;然后把值存到它们所表示的存储空间里&#xff0c;可以用赋值&#xff08;Assignmment&#xff09;语句实现&#xff1a;
char a; //定义一个字符变量a;
int hour,minute; //定义整型变量hour、minute
a &#61; &#39;3&#39;; //给字符变量赋值,字符变量存储空间的值为3
hour &#61; 12; //分别给整型变量赋值&#xff0c;hour存储空间的值为12&#xff0c;minute存储空间的值为58
minute &#61; 58;
注意&#xff1a;变量先声明后使用&#xff0c;编译器必须看到变量声明&#xff0c;才知道a,hour,minute是变量名&#xff0c;各自代表一块存储空间。另外&#xff0c;变量声明中的类型表明这个变量代表多大的一块存储空间&#xff0c;这样编译器才知道如何读写这块存储空间。这里的等号不表示数学里的相等关系&#xff0c;和1&#43;1&#61;2的等号是不一样的&#xff0c;这里的等号表示赋值。在数学上不会有i&#61;i&#43;1这样的等式成立&#xff0c;而在C语言中表示把变量i的存储空间中的值取出来&#xff0c;再加上1&#xff0c;得到的结果在存回i的存储空间中。总结一下&#xff1a;定义一个变量&#xff0c;就是分配一块存储空间并给它命名&#xff1b;给一个变量赋值&#xff0c;就是把一个值保存到这块存储空间中。变量的定义和赋值也可以一步完成&#xff0c;这称为变量的初始化&#xff08;Initialization&#xff09;
char a &#61; &#39;4&#39;;
int hour &#61; 13,minute &#61; 28;
在初始化语句中&#xff0c;等号右边的值叫做Initializer,注意&#xff1a;初始化是一种特殊的声明&#xff0c;而不是一种赋值语句。变量赋的值必须符合它的类型&#xff0c;赋值和变量的类型不符导致编译器报警或报错。
<五>表达式
常量和变量都可以参与加减乘除运算&#xff0c;例如&#xff1a;1&#43;1、 hour-1、hour * 60 &#43; minute、minute/60等。这里的&#43;-*/称为运算符&#xff08;Operator&#xff09;,而参与运算的常量和变量称为操作数&#xff08;Operand&#xff09;&#xff0c;上面四个由运算符和操作数所组成的算式称为表达式&#xff08;Expression&#xff09;
和数学上规定的一样&#xff0c;hour * 60 &#43; minute这个表达式应该先算乘再算加&#xff0c;也就是说运算符是有优先级&#xff08;Precedence&#xff09;的&#xff0c;*和/是同一优先级&#xff0c;&#43;和-是同一优先级&#xff0c;*和/的优先级高于&#43;和-。对于同一优先级的运算从左到右计算&#xff0c;如果不希望按默认的优先级计算则要加()括号&#xff08;Parenthesis&#xff09;。例如(3&#43;4)*5/6应先算3&#43;4&#xff0c;再算*5&#xff0c;再算/6。
int total_minute,total;
total &#61; total_minute &#61; hour * 60 &#43; minute;
计算顺序是先算hour * 60 &#43; minute得到一个结果&#xff0c;然后算右边的等号&#xff0c;就是把hour * 60 &#43; minute的结果赋给变量total_minute&#xff0c;这个结果同时也是整个表达式total_minute &#61; hour * 60 &#43; minute的值&#xff0c;再算左边的等号&#xff0c;即把这个值再赋给变量total。同样优先级的运算符是从左到右计算还是从右到左计算称为运算符的结合性&#xff08;Associativity&#xff09;。&#43; - * /是左结合的&#xff0c;等号是右结合的
在C语言中&#xff0c;等号左边的表达式要求表示一个存储位置&#xff0c;而不是一个值。注意&#xff1a;有的表达式既可以做左值也可以做右值&#xff0c;而有的表达式只能做右值。
了解语法树&#xff0c;什么是语法树&#xff1f;我个人理解&#xff0c;根据不同的语法规则&#xff0c;把复杂的程序简单化&#xff0c;转化成一个个替代符&#xff0c;然后再生产指令。
运算符要求左右两边的操作数类型一致。C 语言规定了一套隐式类型转换规则。
1、假设变量x和n是两个正整数&#xff0c;我们知道x/n这个表达式的结果要取Floor&#xff0c;例如x是17&#xff0c;n是4&#xff0c;则结果是4。如果希望结果取Ceiling应该怎么写表达式呢&#xff1f;例如x是17&#xff0c;n是4&#xff0c;则结果是5&#xff1b;x是16&#xff0c;n是4&#xff0c;则结果是4。
#include
int main(void)
{
        int x,n,a,b,c;
        printf("Please input x and n numbers:\n"); /*提示输入x和n的值*/
        scanf("%d%d",&x,&n); /*输入两个整型数值&#xff0c;&x,&n的地址*/
        a&#61;x/n; /*x除以n取整&#xff0c;然后将值赋值给a*/
        b&#61;x%n; /*取x除以n的余数&#xff0c;然后将余数赋值给b*/
        if(b>&#61;1&&b<&#61;9) /*对余数判断&#xff0c;如果不被整除&#xff0c;则取最大限度值&#xff0c;将a加1*/
        {
                c &#61; a&#43;1;
                printf("%d\n",c);
        }
        else /*如果被整除&#xff0c;结果按原样输出*/
        {
                c &#61; a;
                printf("%d\n",c);
        }
                                                                    
        return 0;
}
<六>字符类型与字符编码
字符常量或字符型变量也可以当作整数参与运算&#xff0c;例如&#xff1a;
printf("%c\n",&#39;c&#39;&#43;2);
执行结果输出e
我们知道&#xff0c;符号在计算机内部也用数字表示&#xff0c;每个字符在计算机内部用一个整数表示&#xff0c;称为字符编码&#xff08;Character Encoding&#xff09;&#xff0c;目前最常用的是ASCII码&#xff08;American Standard Code for Information Interchange&#xff0c;美国信息交换标准码&#xff09;,ASCII码中字符c是99&#xff0c;计算&#39;c&#39;&#43;2这个表达式&#xff0c;应该按ASCII码把&#39;c&#39;当作整数值99&#xff0c;然后加2得到101&#xff0c;然后printf把98这个整数值当作ASCII码来解释&#xff0c;要求输出的是字符&#xff0c;然后打印出整数值101对于ASCII码的字符e。
参考《Linux C编程一站式学习》