C语言学习笔记

C语言学习笔记

目录

  1. 第一章

  2. 第二章

第一章

复习题:
源代码包含了程序员所编写的使用任何编程语言编写的代码。
目标文件包含了机器语言代码
可执行程序是完成的机器语言代码
定义程序目标-->设计程序-->编写代码-->编译-->运行程序-->测试和调试程序-->维护和修改程序
编译器的任务:把源代码转化成等价的机器语言。
链接器的任务:把编译好的目标代码和库代码以及启动代码链接起来,生成可执行文件

5.:练习题(code_0):

#include <stdio.h>
int main()
{
    double a;
    printf("Please input a value whose unit is inch: ");
    scanf_s("%lf",&a);
    getchar();
    a = a*2.54;
    printf("\n%.3f",a);
    getchar();
}

第二章

C代码的构成:

​ C_Source_Code = {预处理指令(如:#include)–>

​ int main():{语句(函数的内容)}–>

​ function a():{语句}–> function b():{语句}–>… }

语句 = {标号语句,复合语句,表达式语句,选择语句,迭代语句,跳转语句}

数据类型:见下一章节
代码分析:以该段代码例

a = a*2.54是一个赋值语句,其中左边的a称为左值(lvalue),右边的值称为右值(rvalue).=右边用于计算并读取值,然后在把这个值传递给=左边的变量,作为其新的值。

printf()中实参数为"\n%.3f",其中\n为换行符, %3.f中%用于提醒程序此处用于打印一个变量,3.f意思是打印一个保留小数点后三位的浮点数。此处效果类似于python中的

a = 2.3434343
print(f"\n{'{:.4}'.format(a)}")  # outputs: 2.343

并且printf();是一个表达式语句。

C的关键字
autoexternshortwhile
breakfloatsigned_Alignas
caseforsizeof_Alignof
chargotostatic_Atomic
constifstruct_Bool
continueinlineswitch_Complex
defaultinttypedef_Generic
dolongunion_Imaginary
doubleregisterunsigned_Noreturn
elserestrictvoid_Static_assert
enumreturnvolatile_Thread_local

关键字不可以被用作变量名或者函数命,比如你定义了一个函数叫做printf()那么它就会在编译的时候覆盖原本的printf()的作用。

eg:

#include "stdio.h"
void scanf(int num);

int main()
{
    int a = 1;
    scanf(a);
    return 0;
}

void scanf(int num)
{
    printf("The number a is : %d",num);
}
outputs:error: conflicting types for 'scanf'

scanf()函数会读取缓冲区(buffer)中的数据,如果遇到空白符,那就跳过当前的,并进入下一个变量。注意你在输入结束的时候数据流结尾会带上一个\n,这就导致你在循环中反复使用scanf时会出错。

e.g.

#include<stdio.h>
#include <stdlib.h>

int main(void)
{
    char a,b;
    while(scanf("%c %c",&a,&b) != EOF)
    {
        printf("a = ");
        putchar(a);
        printf(" b = ");
        putchar(b);
    }
    return 0;
}
/*
a 输入
b 输入
a = a b = ba 此处输入了一个a
a = 
 b = a
 */

先输入a再输入b,结尾此时缓冲区里面有a,b,\n。之后输出前两个a,b。之后再输入a,缓冲区里面\n后面接了一个a,此时按下enter,那么缓冲区中a后面再多一个\n。那么scanf把\n传到a的地址中,'a’传到b的地址中。从而有了

a = 
b = a

这样的输出。(以上默认你的输入和它要求的格式匹配)。

本章复习题:
  1. C语言的基本模块是函数
    
    

第三章

浮点数: 浮点数在C中的储存方式为

符号(+/-)exponent(指数):x尾数:.xxxxxx

如3.1415被记录为 + . 31415 ∗ ( 1 0 1 ) + .31415*(10^1) +.31415(101)

int类型: 范围 − 2 31 ∼ 2 31 − 1 -2^{31}{\sim}2^{31}-1 2312311,占4个字节32bit,

打印 unsigned int类型的值的时候要使用%u,若是usigned long int%lu,usigned long long int%llu.

%x是打印为对应的16进制整数,%o是打印为对应的8进制整数。

#include <stdio.h>
int main(void)
{
    unsigned int un = 3000000000;
    short end = 200;
    long big = 65537;
    long long verybig = 12345678908642;

    printf("un = %u and not %d\n",un,un);
    printf("end = %hd and %d\n",end,end);
    printf("big = %ld not %hd\n",big,big);
    printf("verybig = %lld not %d\n",verybig,verybig);
    return 0;
}

//结果 编译器版本为clang 13.0 系统:macos 12.2
un = 3000000000 and not -1294967296
end = 200 and 200
big = 65537 not 1
verybig = 12345678908642 not 1942899938

h修饰符是把一个整型阶段short类型. big = 65537 = 00000000 00000001 00000000 00000001(二进制)被截断为short类型后按照00000001打印出来,所以结果为1,同理其他的。

char类型

注意,如果是单个字符

char a;

那么有

a = 't' ;//True
a = "t" ;//False,because character is not string,the \"",means a string
a = t ;//False,because t is a variable here

char 变量实际上是被储存为一个整数,其值为字符对应的ASCII码。

i.e.

char a = 65;
printf("%c",a); //outputs: A

转义字符

\a,\f,\n,\r,\t,\v,\\,\',\",\?,\0oo,\xhh

用宏定义进行整数格式化输出

#include <stdio.h>
#include <inttypes.h>
int main()
{
  int32_t me32; //me32 is a 32-bit signed integer variable
  me32 = 45933945; 
  printf("me32 = %" PRId32 "\n",me32); // PRID32 是一个宏定义,会被替换为inttypes中定义的d,这样的好处是一定是按照32位来输出的,不会因为计算机位数改变而改变
  printf("me32 = %d\n",me32);//outputs:45933945 上面一行输出也一样,测试环境同上
}
float、double and long double

float可以保证至少6位的有效数字,注意是保留上面***浮点数***一节中的小数中间的前6位数字如0.123456789,只保证123456的精度。

对于233.3434343也是只保证233.343这几个的精度。

double至少可以保证10位有效数字,为64位的变量(8字节)。

浮点数的声明方法:
double a,b,c,d,e;
a = 3232.322; //赋值方法一
b = 2.32E+12;//赋值方法二
c = 2.99e-3;//赋值方法(表示方法)三
d = .2; //d = 0.200000
e = 100. // outputs: 100.000000
//Remark: c = 2.99 e-3 是错误的,和E(e)之前不可以有空格

Remark: 浮点数常量默认被编译器认为是double类型,在浮点数常量后添加后缀f或者F可以使其被识别为float类型,同理加上后缀l或L,会被识别为long double

e.g.

#include <stdio.h>
int main(void)
{
    float a = 6.f;   //6f不可以,因为6被识别为int类型常量,f后缀对int类型常量无效,同理,L.
    long double b = 0.323l;
    printf("%f %Lf\n",a,b);  //outputs: 6.000000 0.323000
    printf("%d",a); // 0,这里并不是将小数点部分以后截断,而是按照转换int的内存信息的方式转换这块记有float a的内存的信息,然后输出,所以结果为0
    return 0;
}

浮点数格式化输出方法: %f,%a,%e

e.g.

double c;
c = 5.32e-5;
printf("%f\n",a);
printf("%a\n",a);
printf("%e\n",a);
// outputs:
0.000053
0x1.be46214c80e21p-15
5.320000e-05

%a是把浮点数以16进制输出,后面的p-15意思是 0 x 1. b e 46214 c 80 e 21 ∗ 2 − 15 0x1.be46214c80e21*2^{-15} 0x1.be46214c80e21215

浮点数的范围

#include <stdio.h>
#include <float.h>
int main(void)
{
    printf("%e %e\n",FLT_MAX,FLT_MIN);
    printf("%e %e",DBL_MAX,DBL_MIN);
    return 0;
}
/*outputs:
3.402823e+38 1.175494e-38
1.797693e+308 2.225074e-308
*/

其中FLT_MAX,FLT_MIN,DBL_MAX,DBL_MIN为头文件float.h中的宏定义,其分别代表了float类型的最大值和最小值,double类型的最大(小)值。

所以浮点数是有范围的,如果浮点数的值超过了它的最大值,那么那么称之为上溢(overflow),在C中,该数会被赋值为inf

#include <stdio.h>
#include <float.h>
int main(void)
{
    printf("%Le",LDBL_MAX+1.00e+308);
    return 0;
}
//outputs: inf

假设a是一个float所能够表示的最小的float变量,然后对a进行一次运算使其指数指数进一步减小,此时a的有效位数会下降,既a损失了最高精度,称这个为下溢(underflow),如a = 0.1234E-10; a/10;outputs:a = 0.0123E-10(这只是一个例子,不适用于实际上的C).其中损失了最后一位的4,因为此时已经到达了浮点数的指数所能显示的最小值-10(我们假定是-10,实际上不是,而且情况会更加复杂),那么为了实现a/10的效果只能改变E前面0.1234变更为0.0123(向右移动一位),此时精度发生损失。

下面是取a =1.175494e-38(float能准确描述的最小值)的时候,a的精度是如何损失的

#include <stdio.h>
int main(void)
{
    float a = (float)1.175494E-38;
    printf("%e",a);
    for(int ix = 1;ix <10;ix++)
    {
        a = a/10;
        printf("\n%e",a);
    }
    return 0;
}
outputs:     | 损失的精度位数
1.175494e-38 | 0
1.175493e-39 | 1
1.175493e-40 | 1
1.175549e-41 | 3
1.175689e-42 | 3
1.177091e-43 | 4
1.121039e-44 | 6
1.401298e-45 | 7
0.000000e+00 | all
0.000000e+00 | all

其它浮点数计算的误差

#include <stdio.h>
int main(void)
{
    float a ,b;
    double c;
    a = 2.0E20f;
    c = 2.0E20;
    b = (2.0E20f) +1.0f;
    printf("%f\n",c);
    printf("%f\n",a);
    a = b - (float)2.0E20;
    printf("%.26f",a);
    return 0;
}
outputs:
200000000000000000000.000000   c作为double变量就没有问题,因为c的精度更高
200000004008175468544.000000   这一步有误差
0.00000000000000000000000000   这一步没有误差,与C Primer Plus上说的不一致,可能是编译器版本比较新的关系
复数
#include <stdio.h>
#include "complex.h"
int main(void)
{
    complex float a;
    a = 1.0+2.0I;
    printf("%f+%fi", crealf(a), cimagf(a));
    return 0;
}

在complex中用I(大写的 i 表示 − 1 \sqrt{-1} 1 ),用i也可以,但是a = 1.0 + 2.0 * i不可以这样i会被编译器认为是变量,不再是 − 1 \sqrt{-1} 1 .

布尔值

_Bool类型,在C中用1表示true,0 表示false. 所以_Bool其实也是整型。

小结

C中一共有11种关键字:

intlongshortunsignedcharfloatdoublesigned_Bool_Complex_Imaginary

对于同一个整型,unsigned的类型所能够表示的范围(在正整数域上,要大于signed类型),因为第一位不再用于表示正负,也用来表示大小了。

long double的精度不一定高于double,得看你的电脑是几位的,但是最高不超过8字节。

可以使用sizeof()函数查看当前变量类型占用几个字节,或者查看limits.h 和float.h中有相关的类型限制的信息。

复数和虚数的声明方法(不引入complex.h)的情况下

float _Complex
double _Complex
long double _Complex
float _Imaginary
double _Imaginary
long double _Imaginary
小技巧:

在命名变量名的时候前面加上一些表示比如unsigned short变量有前缀表示它是us_ 可以帮助自己通过变量命了解这个变量的类型,提高代码可读性。

字符串的格式化输入/输出

C存储字符串的方式之一是使用字符数组char a[]

注意,每一个字符占据一个比特,且在这个字符数组中,其末尾一定是\0,\0是一个非打印字符,C在打印到\0时会停止打印

#include<stdio.h>

int main(void)
{
    char a[] = {'a','b','b','\0','v','d'};
    printf("%s",a);
    return 0;
}
/* outputs:
abb
*/

可以从示例中看到\0后面的字符不再被打印。

并且scanf在读取字符串的时候读到空格‘ ’,就会停止。

#include<stdio.h>

int main(void)
{
    char a[20];
    scanf("%s",a);
    printf("%s",a);
    return 0;
}
/*
input: hoiwdh nwdiw
output: hoiwdh
*/

C在limits.h 和floats.h中有一些符号常量,用于告诉用户,该整型和浮点数的大小限制(位数,字节数等)。详情见C Primer Plus 67页
目前先更新到这里,润了😇

·

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值