一、随机数
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
srand((size_t)time(NULL));
for (size_t i = 0; i < 10; i++)
{
printf("%d\n", rand()%51+50);
}
}
二、函数
- C语言中形参不可赋值:在定义函数时指定的形参,在未出现函数调用时,它们并不占内存中的存储单元,因此称它们是形式参数或虚拟参数,简称形参,表示它们并不是实际存在的数据,所以,形参里的变量不能赋值。
- 参数单向传递:实参变量对形参变量的数据传递是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给实参。在调用函数时,编译系统临时给形参分配存储单元。调用结束后,形参单元被释放。
- 实参单元与形参单元是不同的单元。调用结束后,形参单元被释放,函数调用结束返回主调函数后则不能再使用该形参变量。实参单元仍保留并维持原值。因此,在执行一个被调用函数时,形参的值如果发生改变,并不会改变主调函数中实参的值。
- 函数声明:如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面,应该对被调用的函数做声明。[extern] 数据类型 函数名(参数);
- 在 main 函数中调用 exit 和 return 结果是一样的,但在子函数中调用 return只是代表子函数终止了,在子函数中调用exit,那么程序终止。
三、头文件
- 头文件.h的作用:
1.全局变量的定义;
2.函数的声明。 - 防止头文件重复包含:为了避免同一个文件被 include 多次, C/C ++ 中有两种方式,一种是 #pragma once 方式,一种是#ifndef方式。
- 把函数声明放在头文件 xxx.h中,在主函数中包含相应头文件,在头文件对应的 xxx.c 中实现 xxx.h 声明的函数。
//每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线
#ifndef _HEAD_H_
#define _HEAD_H_
//把头文件的内容都放在#ifndef和#endif中,不管头文件会不会被多个文件引用。
#endif
四、指针 (地址)
-
*
在不同的场景下有不同的作用:*
可以用在指针变量的定义中,表明这是一个指针变量,以和普通变量区分开;使用指针变量时在前面加*
表示获取指针指向的数据,此时是一个取值运算符。int a = 10; int* p = &a;//p是一个指针变量 *p = 20;//*取值运算符
- 在 32 位操作系统下所有指针类型是 4 个字节大小;在 64 位操作系统下所有指针类型是 8 个字节大小。
- 在定义指针类型时一定要和指向的变量的类型保持一致。
- 野指针:指针变量指向一个未知的空间。
int* p=100;指针p的值是100,100是某个变量的地址,但该变量的值未知。
程序中允许存在野指针,但操作野指针对应的内存空间可能报错(操作系统将0-255作为系统占用,不允许进行访问操作)。 - 空指针:野指针和有效指针变量保存的都是数值,为了标志此指针变量没有指向任何变量 ( 空闲可用 ) , C 语言中,可以把 NULL 赋值给此指针,这样就标志此指针为空指针。int* p=NULL;
NULL是一个值为0的宏常量,所以空指针是指在内存地址编号为0的空间。#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif
- 万能指针:void* p;万能指针可以指向任意变量的内存空间,但是操作该指针时需要转换为具体类型。
int a = 10; void* p = NULL; p = &a;//正确 p = (void*)&a;//正确 //*p = 20;//错误 *(int*)p = 20;//正确,即*((int*)p) = 20;
- const 修饰指针(就近原则)
1、 const 修饰指针类型可以修改指针变量的值,不可以修改指针指向内存空间的值。
2、 const 修饰指针变量可以修改指针指向内存空间的值,不可以修改指针变量的值。
3、 const 修饰变量在C语言中不安全:const修饰变量后,该变量可通过指针进行修改。//const 修饰变量在C语言中不安全:const修饰变量后,该变量可通过指针进行修改 const int a = 10; int* p = &a; *p = 20; printf("%d\n", a);//20 // const 修饰指针类型可以修改指针变量的值,不可以修改指针指向内存空间的值。 int b = 30; const int* p1 = &a; p1 = &b;//正确 //*p1 = 40;//错误 printf("%d\n", *p1);//30 //const 修饰指针变量可以修改指针指向内存空间的值,不可以修改指针变量的值。 int* const p2 = &a; *p2 = 50;//正确 //p2 = &b;//错误 printf("%d\n", a);//20 //const 修饰指针类型和指针变量时,指针变量的值和指针指向的内存空间的值都不可变 const int* const p3 = &a; //p3 = &b;//错误 //*p3 = 50;//错误
★ CPU访问内存时需要的是地址,而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址。编译和链接过程的一项重要任务就是找到这些名称所对应的地址。
★ %#X 表示以十六进制形式输出,并附带前缀0X。C语言中有一个控制符%p,专门用来以十六进制形式输出地址 , 不过%p的输出格式并不统一,有的编译器带 0x 前缀,有的不带。
const int num = 10;
int* p4 = &a;
printf("%p\n", p4);//008FF6F8
printf("%#X\n", p4);//0X8FF6F8