scanf函数的使用
scanf()这个函数是有返回值的,scanf 和 wscanf 都返回成功转换和分配的字段数;返回值不包括已读取但未分配的字段。返回值 0 表示未分配任何字段。返回值为 EOF (-1)表示错误,或者在第一次尝试读取字符时遇到文件结束字符或字符串结尾字符。
这里就可以很好理解加粗体的意思了,scanf函数遇到空格就不读取了,所以两个字符数组的返回值都是1。那么有没有办法让scanf读取空格呢?其实是有的:scanf("%[\n]s",arr);就是在%s中间加上[\n],这么写的意思就是让它一直读到\n才停止。
这里返回值也是一,因为它把空格也当成了一个字符,跟abc的地位是一样的。
逗号表达式
逗号表达式从左向右依次计算,最后一个表达式的结果是整个表达式的结果。
a的值最终是最后一个表达式,也就是c的值。
static
static的意思是静态的,它可以修饰三种类型。
1.static修饰局部变量:一般局部变量都是放在内存中的栈区,但是经过static修饰以后就放到了静态区。
通过这个例子我们就能知道,static修饰过的局部变量是不会销毁的,下一次要用的时候直接用。
2.static修饰全局变量,在讲extern的时候我们说过test.c文件可以调用add,c文件中的变量,这里的变量当然是一个全局变量。这体现了全局变量的外部链接属性,而经过static修饰后就变成了内部链接属性,这时extern就不起作用了。
3.static修饰函数,与2是类似的,正常情况下我们可以extern int Add(int x,int y);正常调用外部函数,用static修饰后就不能调用了。
内存
C/C++程序中,内存是分为栈区,堆区,静态区的,栈区是存放临时变量的,堆区是进行动态内存管理的,静态区是存放全局变量的。
定义宏
在C语言中,宏定义是在程序编译之前被处理的预处理器指令,用来简化程序的开发和维护。宏定义使用#define
关键字来定义,一般形式如下:
#define 宏名 替换字符串
其中,宏名
就是定义的宏的名称,替换字符串
就是该宏所要代表的字符串。
例如,定义一个名为PI
的宏,表示圆周率:
#define PI 3.1415926
在程序中,可以使用PI
来代替3.1415926
,从而使程序更加清晰和易于理解:
double radius = 5.0;
double perimeter = 2 * PI * radius;
在宏定义中,也可以使用参数,例如:
#define MIN(x, y) ((x) < (y) ? (x) : (y))
该宏定义了一个名为MIN
的宏,可以用来求两个数的最小值,其表达式为:MIN(a, b)
,其中a
和b
为要比较的两个数。这个宏被展开后,就相当于 C 代码中的一个函数。
宏定义的好处是可以简化代码,但也有其缺点,常见的问题包括宏定义的作用域、宏定义会带来副作用等。因此,在使用宏定义时需要注意一些细节。
地址:指针
32位机器上有32位地址线,每个地址线都可以产生两种(1/0)电信号,这样就会有2^32个地址号,这里的地址号其实就跟我们的门牌号是一样的,一个地址号相应管理一个字节的空间,于是这样就能管理2的32次方的字节的空间,换算一下就是4GB,而64位机器上就可以管理16GB的空间。
结构体的定义和使用
struct stu {
char name[10];
int age;
}stu1;
void print(struct stu* p1) {
printf("%s %d\n", p1->name, p1->age);
}
int main() {
struct stu stu2;
struct stu stu1 = {"xiaoming",12 };
struct stu* p1 = &stu1;
print(p1);
printf("%s %d", stu1.name, stu1.age);
return 0;
}
结构体尽量定义在主函数外面,普通函数的上面,因为普通函数用的时候也方便。创建变量的时候可以直接在创建的结构体后面定义,也可以在主函数中创建。因为结构体写起来比较麻烦,所以可以用typedef重新定义一下。
typedef struct stu {
char name[10];
int age;
}Stu;
今天先写到这吧。