*** 初识C语言篇—易错点总结***
不允许在同一个作用域中定义多个相同名称的变量
比如:在一个班级中存在两个名字相同的学生王帅,当老师点王帅回答问题时,那个回答就冲突了
允许在不同的作用域中定义多个不同名称的变量
比如:两个班级中各有一个王帅,老师在A班中点王帅回答问题,不会有任何歧义
不同作用域中定义的变量,在访问时采用就近原则。
比如:你们村有一个小伙伴名字叫刘德华,那你在你们村喊刘德华时,你们村的刘德华就会跑过来响应你,而我们世界级别人见人爱的天王他不会理你,因为距离远听不见,但是两个刘德华可以同时存在这个 世界上,只要不在一个村,就不会冲突。
main函数是程序的入口,一个工程有且仅有一个main函数。
计算变量或使用类型创建的变量的大小—单位为字节
计算机是以二进制存放数据的,1byte = 8 bit
sizeof(char) = 1;
sizeof(short) = 2;
sizeof(int) = 4;
sizeof(long) = 4;
sizeof(long long) = 8;
sizeof(float) = 4;
sizeof(double) = 8;
如果一个变量是局部变量未初始化,那么它的值是随机的
见1.
c语言中的常量一般有:
const int i = 10; 仍然为变量,只不过在c语言中在语法层面限制,值无法直接改
#define MAX 100 //define定义符号最好大写
printf("max = %d\n", MAX);
enum Sex
{
MALE,
FEMALE,
SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main(){
//枚举常量演示
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
//注:枚举常量的默认是从0开始,依次向下递增1的
}
注:c语言无字符串类型
“hello.\n”
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
易错:char ch = “abc”;(错误),在c语言中我们我们可以将字符串放在字符数组里,例如
char arr1[] = “bit”;
char arr2[] = {‘b’, ‘i’, ‘t’};
int main()
{
char arr1[] = "bit";
char arr2[] = {'b', 'i', 't'};
char arr3[] = {'b', 'i', 't', '\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
上述代码中,其实arr1的最后还隐藏包含了\0,相当于arr3
arr1和arr3中有4个字符,而arr2只有3个字符
(因为我们打印格式为%s,是专属字符串打印,字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。)
当我们打印arr1,arr3时,arr1和arr3中有4个字符,打印时遇到’\0’就会停止
而我们打印arr2时,printf会不断读取字符到%s中去,直到遇到’\0’才停止所以我们打印arr2时,后面会出现随机的一些字符。
库函数strlen(“a”)—>返回字符串的有效长度。
strlen函数在读取字符串时,一旦遇到’\0’就会停止,不将’\0’包含在内计算出字符串长度。(头文件:#include
)
#include
#include
int main()
{
char arr1[] = "bit";
char arr2[] = { 'b', 'i', 't' };
char arr3[] = { 'b', 'i', 't','\0' };
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
printf("%d\n", strlen(arr3));
return 0;
}
打印结果:
上述原理同理打印字符串,因为strlen函数会从前向后依次读取字符串,直到遇到’\0’才停止,返回不包括’\0’在内的字符串长度。
例题:
int main()
{
char arr[] = {'b', 'i', 't'};
printf("%d\n", strlen(arr));
return 0;
}
strlen是用来获取字符串的有效长度的,结尾标记’\0’不包含在内。
strlen获取的规则非常简单:从前往后依次检测,直到遇到’\0’是就终止检测。
而上体中arr是一个字符数组,不是一个有效的字符串,因为后面没有放置’\0’,因此strlen在求解时,将有效字符检测完之后,还会继续向后检测,直到遇到’\0’是才终止
转义字符 | 释义 |
---|---|
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\’ | 用于表示字符常量’ -------printf("%c",’/’’), 如果写成printf("%c",’’’)会误以为前两个’是一个字符串 |
\“ | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。 如: \130 ,将八进制的130转化为十进制88,对应的ASCII码为X,打印X。易错:\090,不是\ddd,因为八进制数字不可能有9 |
\xdd | dd表示2个十六进制数字。 如: \x30 0 |
例题1:
//问题1:在屏幕上打印一个单引号’,怎么做?
//问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?
printf("%c\n", '\'');
printf("%s\n", "\"");
例题2:
printf("%d\n", strlen(“c:\test\628\test.c”));
程序输出什么:
printf("%d\n", strlen(“c : \t e s t \62 8 \t e s t . c”));
易错:
1.转义字符算一个字符,比如\t
2.\ddd中ddd的数字只可能为0-7,八进制数字只可能为0-7,所以\62算一个字符,而不是\628算一个字符
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
scanf("%d,%d", &num1, &num2);
scanf("%d%d", &num1, &num2);
乍一看好像没什么区别,其实。。。
必须要满足格式相符!!!
第一个输入框:2 3
第二个输入框:2,3
第三个输入框:2 3(默认情况下必须输入空格)
int arr[10];
int arr[10] = {0, 1, 2, 3};
int arr[10] = {0};
int arr[10] = {1};
第一个为未初始化,数组每个元素都为随机值;
第二,三,四个为不完全初始化,默认初始化已给元素值,其余元素默认初始化为0(比如,第四个初始化第一个元素为1,其余元素默认为0);
易错:
char arr[3] = {'a', 'b', 'c'};//正确
char arr[3] = "abc";//错误,因为字符串中最后隐含有'\0', 应该定义 char arr[4] = "abc"
int arr[] = {0, 1, 2, 3};
数组可以通过初始化来确定大小
int n = 10;
int arr[n] = {0, 1, 2, 3};
最好不用变量来定义数组大小,c99之后部分编译器支持
int a = 10;
sizeof(a) = 4;
sizeof(int) = 4;
sizeof(10) = 4;
exp1, exp2, exp3, …expN
从左到右依次计算,整个逗号表达式的结果是最后一个表达式的结果。
例题:
int a = 3;
int b = 5;
int c = 10;
int d = (a+2, b=a-3, c=b+4);
计算d,首先必须加大括号才是表示里面一起为一个逗号表达式,它的结果赋值给d,否则会被以为重定义变量。
a+2为5,未赋值,无意义。
b = a - 3 = 3 - 3 = 0。
c = b + 4 = 0 + 4 = 4。
所以最后取最后一个表达式的结果4赋值给d。
register int a = 10;
&a;//错误
原本a是储存在内存中的地址编号,但是此时储存在寄存器里,寄存器不能取地址。
#include
void test()
{
//static修饰局部变量
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for(i=0; i<10; i++)
{
test();
}
return 0; }
static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。
//add.c
static int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);//错误
return 0;
}
一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
//add.c
static int Add(int x, int y) {
return c+y; }
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0; }
一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
.
static的特性:
static修饰变量
a. 函数中局部变量:
声明周期延长:该变量不随函数结束而结束
初始化:只在第一次调用该函数时进行初始化
记忆性:后序调用时,该变量使用前一次函数调用完成之后保存的值
存储位置:不会存储在栈上,放在数据段
b. 全局变量
改变该变量的链接属性,让该变量具有文件作用域,即只能在当前文件中使用
c. 修饰变量时,没有被初始化时会被自动初始化为0
static修饰函数
改变该函数的链接属性,让该函数具有文件作用域,即只能在当前文件中使用
C语言关键字:C语言定义的,具有特定含义、专门用于特殊用途的C语言标识符,也称为保留字。
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。
为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。
int main()
{
int num = 10;
#//取出num的地址
printf("%p\n", &num);//打印地址,%p是以地址的形式打印
return 0; }
注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
打印地址,%p是以地址的形式打印
int* p;
&a;
一般我们称指针p,其实是指针变量p
一般我们称地址,其实为OX~4987938…
其实,我们把地址也称为指针
指针可以认为是一种数据类型,也可以认为是定义出来的指针变量
指针变量的大小取决于地址的大小
32位平台下地址是32个bit位(即4个字节)
64位平台下地址是64个bit位(即8个字节)
int main()
{
printf("%d\n", sizeof(char *));
printf("%d\n", sizeof(short *));
printf("%d\n", sizeof(int *));
printf("%d\n", sizeof(double *));
return 0; }
都相同,由此可见:
指针大小在32位平台是4个字节,64位平台是8个字节。
struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
};
注:
//打印结构体信息
struct Stu s = {"张三", 20, "男", "20180101"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//->操作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps- >id);
struct Stu s = {“张三”, 20, “男”, “20180101”};
用结构体类型来创建一个变量s。