问题
1. 整型存储与字符型存储的问题
整型是以补码存储方式存储的
正整数
正数的补码和原码相同
例如 5
在内存中用 00000000 00000000 00000000 00000101表示
0
0的补码是0x00000000
负整数
负整数的补码是通过将负整数的绝对值的二进制,按位取反后再加1得到的
例如 -5
-5的绝对值是5,在内存中用 00000000 00000000 00000000 00000101表示
按位取反后得到 11111111 11111111 11111111 11111010
加1后得到 11111111 11111111 11111111 11111011
字符型是以补码存储方式存储的
在内存里跟1个字节的整型没什么不同,只不过在表现形式上多了一种表现方式
可以用整数来表示
可以用字符来表示,是因为映射了一个字符
字符的取值范围为 0 ~ 255
例如 -159
-159的绝对值是159,在内存中用 10011111 表示
按位取反后得到 01100000
加1后得到 01100001
等于 97 ,可以用字符'a'来表示
2. 数据的存储
BCD码
是一种二进制的数字编码形式,用二进制编码的十进制代码.
用4位二进制数来表示1位十进制数中的0~9这10个数码。
例如 十进制数 89
用 8421码表示为 10001001 用十六进制表示为 0x89
用 5421码表示为 10111100 用十六进制表示为 0xBC
8412码是最常用的BCD码,将0x11展开为二进制就是0x11在内存中的存储方式
不在C文件中使用
C文件中应用的编码
整型常量 137 在内存中的表示为 00000000 00000000 00000000 10001001 ,可以用 0x89 表示
3.溢出的问题
char c1 = 256;
char c2 = -159;
4.EOF的问题
它是end of file的缩写,表示"文字流"(stream)的结尾
EOF不是特殊字符,而是一个定义在头文件stdio.h的常量,一般等于-1
定义在stdio.h中 #define EOF (-1)
在Linux系统之中,EOF根本不是一个字符,而是当系统读取到文件结尾,所返回的一个信号值(也就是-1)
这个信号是谁给的?
5.转义字符的问题
所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示。
1.'\0141' 代表'a'
- 注意 \0xxx中 xxx的取值范围为 从 000 到777(注意是8进制,没有8和9)
2.'\\' 代表'\'
6.windows和linux下对换行的处理的问题
1. 历史
在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。
- Unix系统里,每行结尾只有“<换行>”,即“\n”;
- Windows系统里面,每行结尾是“<换行><回车>”,即“\n\r”;
- Mac系统里,每行结尾是“<回车>”。
一个直接后果是
- Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;
- Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
2.字符
换行 '\n' 十进制10 0X0A 指回到一行的开头
回车 '\r' 十进制13 0x0D 指开启新的一行
3.实例(liunx下)
printf("abc\rdef\n");
printf("abc\ndef\r");
printf("abc\n\r");
printf("abc\r\n");
7.字符串的问题
字符串常量为什么可赋值给指针?
双引号做了3件事
申请了空间(在常量区),存放了字符串
在字符串尾加上了'\0'
返回地址
8.strlen与sizeof的问题
strlen("\0") 为 0
strlen("\0\0") 为 0
sizeof("\0") 为 2
sizeof("\0\0") 为 3
9.char * p = “hello”;与 char p[] = “hello”;的区别
1. char * p = "hello";
"hello"返回一个地址,赋值给指针p
2.char p[] = "hello"
申请一个连续的空间,刚好存'h''e''l''l''o''\0'6个字符
注意:这里不管最后是不是'\0'结尾,都要添一个'\0'
3.strlen sizeof
char * p = "hello";
char c[] = "hello";
printf("%d\n",sizeof("hello")); 6
printf("%d\n",sizeof(p)); 4
printf("%d\n",sizeof(c)); 6
printf("%d\n",strlen("hello")); 5
printf("%d\n",strlen(p)); 5
printf("%d\n",strlen(c)); 5
10.各种指针的问题
野指针 : 有指向,但是指向是随机分配的
空指针 : 有指向, 指向的是编号为0的地址
对野指针/空指针进行取内容操作,会出现段错误
空指针常量可以用下列表示
1. 整型常量0、0L、'\0'、3 - 3、0 * 17
2. (void*)0
NULL 是一个标准规定的宏定义,用来表示空指针常量。
#define NULL (void*)0
11.二维数组的问题
数组是多个相同类型的元素的集合
如果每个元素为int型数组的话,那么整个数组就是个二维数组.
其实数组没有维度的概念.
想引用一个最小的元素,需要找到它的上一级,如果它的上一级还是数组中的一个元素,那么就一直往上找,直到找到数组名.这样的话就走出一条通路,然后从数组名一级级往下引用,直到那个最小的元素
12.关于想定义一个不知道有多少个元素的数组的问题
定义足够大就可以了,不给具体大小的话,编译器无法给数组分配空间
13.数组变量赋值的问题
无法直接对数组变量赋值.可以一个一个元素赋值
如果是字符数组的话,可以用strcpy来赋值
14.数组名的问题
只有当sizeof(数组名)的时候,数组名才指代数组整个空间
其他情况下,都是指代数组中首个元素的地址
15.变量声明和定义的问题
说起声明的话,只有extern 是用来声明的
其他情况下,都是定义变量
另外结构体类型/枚举类型/共用体类型的声明都是声明
有些博客说定义就是分配内存,声明不会分配内存,这是不准确的的
#define PI 3.1415926
此宏定义没有分配内存
16.类型转换的问题
char/short ->int ->long ->double 会自动转换
float ->double 会自动转换
当然也可以强制类型转换,语法为
(类型名)变量
18.常量表达式和变量表达式的问题
常量与变量的交互产生一个变量
变量与变量的交互产生一个变量(一般情况下会成立,像a^a,结果为0)
常量与常量的交互产生一个常量