C语言入门笔记(4)
二维数组
1 | int a [3] [5] |
代表定义了一个3行5列的二维数组
但a [2] [4]
指的是数组中第3行第5列的那个元素
因为计算机是从0开始数数的
多维数组也可借此类推
二维数组的初始化
1 | int a [] [5] = { |
列数必须给出,行数可以省略,由编译器来数
每行一个{},逗号分隔
最后的逗号可以存在
如果省略了元素,表示补零
也可以用定位(c99 only)
数组的大小
sizeof可以表示出某个类型或变量在内存中占据的字节数
因此数组的元素个数可以用sizeof(a)/sizeof(a[0])表示
这样表述的好处是,一旦修改数组中初始的数据,不需要再修改遍历的代码
数组的赋值
1 | int a[] = {1,2,3,4,5}; |
这是不可行的
1 | int b[] = int const b[] |
b[]被定义后具有了常属性,不能直接赋值给另一个数组
但可以让b数组遍历读入a数组的每一个元素,完成所谓的复制,代码如下:
1 | int a[4] = {1,2,3,4}; |
结果正确,但有些人遍历输出时也用了i
1 | { |
运行确实没问题,但要指出的是:一专多能是不好的代码
当然也可以用指针,这里不再赘述
遍历
一维数组的遍历可以用一个for循环
1 | for ( i=0; i<3; i++ ) { |
二维数组的遍历则需要用两个for循环
1 | for ( i=0; i<3; i++ ) { |
遍历数组可以做数组的初始化,可以输出数组,可以搜索数组中的元素等等
在遍历时一般用for循环,最好用0和<,而不是1和<=,因为前者遍历时最大的i恰好是数组的最大下标
运算符&
变量的地址
使用&可以获得变量的地址,地址的大小是否与int相同取决于编译器是32位还是64位
1 | printf("%x",&i); |
所以要输出一个变量的地址时,更应该用%p而不是%x,%x只是把地址当成一个16进制的整数,地址并不总和整数相同
数组的地址
1 | printf("%p\n",&a); |
从中我们可以看出地址&a == a == a[0],且相邻的元素差4个字节
指针
指针就是保存地址的变量
1 | int* p == int *p |
两种写法都一样,类型是int,不是int*
1 | int i; |
i的地址传给了*p,也就是说p指向了i
指针变量
普通变量的值是实际的值
指针变量的值是具有实际值的地址
作为参数的指针
1 | int i = 0; |
参数是普通变量的地址
在这个函数内可以通过这个指针访问外面的变量i
运算符“ * ”
*是一个单目运算符,用来访问指针的值所表示的地址上的变量
*P可以做左值和又值
1 | int k = *p; |
数组作为指针
数组变量是特殊的指针,因为数组本身表达地址
因此对于int*p=a,无需用&取地址,但是数组的单元表达的是变量,需要用&取地址
即a == &a[0],指针也可以用[]运算符
下面四种函数原型等价
1 | int sum(int *ar,int n); |
另外在函数参数中数组相当于指针
* 利用指针交换两个数组
代码如下
1 |
|
结果正确
字符类型
char
char是一种整数,也是一种特殊的类型:字符。
用单引号表示的字符字面量:’a’,’1’
‘’也是一个字符
printf和scanf里用%c输入字符
字符的输入输出
1 | int char i = '1'; |
因为’1‘的ASCII编码是49
混合输入
1 | 1.scanf("%d %c",&i,&c); |
二者不同,在于2中读取输入的两个值时,如果有空格会读取空格,空格的ASCII码为32
字符计算
1 | char c ='A'; |
说明一个字符加一个数字得到ASCII码表中那个数之后的字符
1 | int i ='Z'-'A'; |
说明两个字符的减,得到的是它们在表中的距离
大小写转换也可以通过字符计算实现
逃逸字符
用来表达无法印出的控制字符或特殊作用的字符
要指出的是回车和换行是两个动作,只是编译器顺带着换行一起执行了
字符串
1 | char word[] = {'H','e','l','l','o','!','\0'} |
字符串以数组形式存在,以数组或指针的形式访问
\0是结束的标志,它不是字符串的一部分,但它占用一个字节的空间
string.h 里有很多处理字符的函数
两个相邻的字符串常量会相连
1 | printf("123" |
会输出123456
另外不能用运算符对字符串做运算
”a“就相当于对a做了初始化
字符串常量
字符串初始化后便不可变,字符串在内存中是只读的
用指针改变字符串会触发系统的保护机制,引起严重后果
字符串的赋值
1 | char *t = "title"; |
这样做只是让指针s指向了t所指的字符串,并没有产生新的字符串
字符串输入输出
1 | char a[8] |
scanf的读入是不安全的,因为不知道要读入的内容的长度
但可以这样:
1 | char a[8] |
“7”告诉了scanf最多读7个
两个scanf可以连续读入
常见错误
char*a不能直接用,要先对a初始化,否则出不出错就靠运气了
终于码完了。。。
C语言入门篇完结!!!