本文根据浙大翁伯的慕课C语言程序设计基础进行编写,里面添加了许多细节,用心品味,相信会得到一些帮助以及对C语言的新见解。
编译执行C程序
在linux上进行编译执行c程序:
gcc hello.c -o hello
,就会生成一个可执行文件,再输入./hello
,就会启动可执行文件。
注意事项
- C语言不支持嵌套函数定义
- 逗号运算符( , )是C语言运算符中优先级最低的一种运算符,结合顺序是从左至右,用来顺序求值(最后一个逗号后面表达式的值作为整个表达式的值)
c = (a>b, a+b); // 运行后c值为8,因为括号的优先级高于赋值运算符,所以先算括号内的表达式,此时计算结果为最后一个表达式的值,即a+b的值,所以c=8
C99变化
集成初始化
- 可以使用变量给数组赋予长度
- 数组赋值可以指定下标相应的,获得稀疏数组:`
a[10]={
[1]=1, 3, [5]=6};
//a = [0,1,3,0,0,6,0,0,0,0}
变量类型
size_t
size_t
类型是一个类型定义,通常将一些无符号的整形定义为size_t
,比如说unsigned int
或者unsigned long
,甚至unsigned long long
。每一个标准C实现应该选择足够大的无符号整形来代表该平台上最大可能出现的对象大小。
使用size_t
size_t
的定义在<stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, <time.h>
和<wchar.h>
这些标准C头文件中,也出现在相应的C++头文件, 等等中,你应该在你的头文件中至少包含一个这样的头文件在使用size_t之前。 包含以上任何C头文件(由C或C++编译的程序)表明将size_t
作为全局关键字。包含以上任何C++头文件(当你只能在C++中做某种操作时)表明将size_t作为std命名空间的成员。 根据定义,size_t
是sizeof
关键字(注:sizeof是关键字,并非运算符)运算结果的类型。所以,应当通过适当的方式声明n来完成赋值:
n = sizeof(thing);
考虑到可移植性和程序效率,n应该被申明为size_t
类型。类似的,下面的foo函数的参数也应当被申明为sizeof:
foo(sizeof(thing));
参数中带有size_t
的函数通常会含有局部变量用来对数组的大小或者索引进行计算,在这种情况下,size_t是个不错的选择。
适当地使用size_t
还会使你的代码变得如同自带文档。当你看到一个对象声明为size_t类型,你马上就知道它代表字节大小或数组索引,而不是错误代码或者是一个普通的算术值。
size_t()
// %lu 配合size_t输出
printf("%lu\n", );
数组、指针
数组长度
- 使用
sizeof()
int a[] = {
1,2,3,4};
int len = sizeof(a)/sizeof(a[0]);
定义数组
在数组结束位置加一个逗号,方便再向数组后面添加元素。
int a[] = {
0,1,2,};
const
数组
数组变量为const
类型指针,则表明数组的每个单元都是const int
,故必须对数组进行初始化赋值:
const int a[] = {
1,2,3,4,5,};
数组与指针
在函数原型定义中,即函数的参数列表中,数组和指针其实是一样的东西:
// 以下四种函数原型是等价的
int sum(int *arr, int n);
int sum(int *, int);
int sum(int arr[], int n);
int sum(int [], int);
其实,数组变量本身就是表达地址,所以
int a[10];
int *p = a;
在这里无需使用&
取地址符。
但如果是要表达数组单元,因为数组单元是变量,则需要使用&
取地址符“
a == &a[0]; // 对数组的首元素取地址
解释数组不能相互直接赋值的原因
由于数组变量是const
的指针,所以不能被赋值,即
int a[] <==> int * const a=...
常量与变量
总可以是把一个非const
的值转换为常量:
int a = 15;
const int b = a;
b = a + 1; // ERROR!
动态内存分配
如果输入数据时,先由用户输入个数,再输入,则可以动态分配内存:
实例:实现动态数组长度
// 使用malloc函数分配内存,需要导入标准库头文件
#include <stdlib.h>
int *a = (int*)malloc(n*sizeof(int)); // a 为数组
free(a); // 使用完后需要释放分配的动态内存
对于free
,只有申请过的空间才需要释放。
解释:
malloc
函数返回的是void*
类型,需要转换为int*
类型。
运算符
取址符&
&
:获得变量的地址,操作数必须为变量。
例如:
// 使用%p格式化输出,可以获得变量的十六进制地址
int i; printf("%p\n", &i);
注意在不同架构系统下,地址变量的长度有所不同,在x32和x64架构下,整型
int
都是4位,而在x32下,地址长度也为4位,而在x64下,地址长度为8位。
指针
指针类型说明
int* p