初步认识c语言

什么是c语言

  • C语言是一种通用的高级编程语言,由Dennis Ritchie于1972年在贝尔实验室开发。
  • C语言具有简单、高效、可移植、可靠和灵活的特点,因此被广泛应用于操作系统、编译器、游戏开发、嵌入式系统、科学计算以及其他各种领域的软件开发。
  • C语言是一种结构化编程语言,支持面向过程和面向对象编程,提供了丰富的基本数据类型、控制结构、函数库等特性,同时也支持指针和位运算等底层操作。
  • C语言的语法简洁明了,易于学习和使用。

数据类型

常见数据类型

C语言中有多种基本数据类型,包括:

  1. 整型(int):表示整数值,可表示的范围依赖于所用机器的计算能力,一般为-2的31次方到2的31次方-1。

  2. 字符型(char):表示单个字符,占用一个字节的内存空间,可用于存储ASCII码表中的字符。

  3. 短整型(short):表示短整数值,可表示的范围为-2的15次方到2的15次方-1。

  4. 长整型(long):表示长整数值,可表示的范围为-2的31次方到2的31次方-1。

  5. 浮点型(float):表示浮点数,即带小数点的数值,可表示的范围和精度与所用机器的浮点运算能力有关。

  6. 双精度型(double):表示双精度浮点数,比浮点型精度更高,可表示的范围也更大。

此外,C语言还支持一些复合数据类型,如数组、结构体和联合体,以及指针类型,可用于处理复杂数据结构和动态内存分配。


变量与常量

变量

  • 变量就是变化的量
  • 变量分为全局变量与局部变量
//变量与常量
 #include <stdio.h>

int n = 10;//全局变量 
int	main()
{
    int age = 20;//局部变量 
    float weigh = 88.5;

    return 0;
}

  • 同一作用域用变量不能重复定义;局部变量与全局变量可以重复,以局部变量优先
int n = 100; 
int	main()
{
	//int n = 10; 
	int n = 10; 
	printf("a=%d\n",a);//10

    return 0;
}
  • 变量定义后就要初始化,因为c语言中变量默认值是随机的

练习

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>

//计算两个数的和 
int main()
{
	 int n1 = 0,n2 = 0;
//输入两个整数
	printf("输入两个整数:");//输出函数 
	scanf("%d %d",&n1,&n2);//输入函数必须取地址 
// vs使用scanf函数会报错 ,直接在代码第一行define一个宏,不要使用scanf_s 

//	求和
	int sum = n1 +n2;
//	输出结果
 	printf("sum=%d\n",sum);
 
 	return 0;
 } 

常量

  • c语言中,常量分为以下几种:
    • 字面常量
    • const修饰的常变量
    • #define定义的标识符常量
    • 枚举常量
#include<stdio.h> 
#define N 100 
//常量
//	枚举常量 
enum Gender
{
	F,
	M
 } ;
  
 int main()
 {
// 	字面常量 
 	6;
// 	const修饰的常变量 
	int a = 1;
	a = 6;
	const int b = 1;//常变量本质是变量,但是不能被修改,有常量的属性 
	//	b = 6;
//	标识符常量
	int c = N;
	printf("%d\n",c);
	
	enum Gender m = M;
	 
 	return 0;
 }

字符串+转义字符+注释+命名规范

字符串

  • 在C语言中,字符串字面量指的是用双引号括起来的一串字符,也就是字符串常量。例如,"Hello, world!"就是一个字符串字面量。

  • 字符串字面量在C语言中是常量,它们在程序运行期间是不能修改的。它们被存储在程序的静态存储区域中,通常是在可执行文件的数据段中。程序在运行时可以通过指向字符串字面量的指针来访问它们。

  • c语言中没育字符串类型,通常使用字符数组保存字符串

#include<stdio.h> 
#include<string.h> 

int main()
{
//	字符串
	char arr1[] = "abcde"; //字符串""以\0为结束标记 
	printf("%s\n",arr1);
	char arr2[] ={'a','b','c','d','e','\0'}; //这种形式没有结束标记 
	printf("%s\n",arr2);
	
//	strlen():求字符串长度的一个函数,在头文件string.h中
 	int len = strlen(arr2);
 	printf("%d\n",len);
	
	return 0;
}

转义字符

在C语言中,转义字符是用反斜杠(\)作为前缀的特殊字符序列。转义字符的作用是用来表示一些无法直接输入的字符,如换行符、制表符、双引号等。

下面是常见的一些转义字符:

  • \n:表示换行符(Newline)
  • \t:表示制表符(Tab)
  • \b:表示退格符(Backspace)
  • \r:表示回车符(Carriage return)
  • \f:表示换页符(Form feed)
  • \v:表示垂直制表符(Vertical tab)
  • \:表示反斜杠字符本身
  • ':表示单引号字符本身
  • ":表示双引号字符本身
#include<stdio.h> 

int main()
{
//	转义字符
	char arr1[] = "abcden"; 
	printf("%s\n",arr1);
	char arr2[] = "abcde\n";  
	printf("%s\n",arr2);
	
	return 0;
}

注释

在C语言中,有两种注释方式:单行注释和多行注释。

  1. 单行注释
    单行注释以//开头,后面跟着注释内容。单行注释可以在一行代码的末尾使用,也可以在一行代码的中间使用。单行注释会忽略后面的所有文字,直到行末结束。
int a = 10; // 这是一个单行注释,用于解释变量a的含义
  1. 多行注释

多行注释以/*开头,以*/结尾,中间是注释内容。多行注释可以跨多行使用,可以注释掉一段代码或多个语句。

/*
这是一个多行注释
可以跨多行使用
用于注释掉一段代码或多个语句
*/

int a = 10; // 这行代码被多行注释包围,被注释掉了
  • 注释中的内容不会被编译器解释和执行,因此可以用于解释代码、调试、隐藏代码等目的。注释的作用是提高代码的可读性和可维护性。

命名规范

在C语言中,函数名称、参数名称和变量名称需要遵循以下命名规则:

  1. 只能使用字母、数字和下划线_字符。
    2.必须以字母或下划线_字符开头。
    3.名称长度不能超过255个字符。
    4.区分大小写。
    此外,还有一些命名约定应该遵循,以提高代码的可读性和可维护性:
  2. 函数名称应该以动词开头,以表明其执行的操作。例如,calculate_sum 表示计算总和的函数。
  3. 参数和变量名称应该以名词或形容词开头,以描述它们所代表的内容。例如,length 表示长度,max_value 表示最大值。
  4. 多个单词组成的名称应该使用下划线_字符分隔,而不是使用空格或驼峰命名法(camel case)。例如,max_value 表示最大值,而不是 maxValueMaxValue
  5. 避免使用关键字或保留字作为名称。例如,不能使用 intwhile 作为变量名。
  6. 使用有意义的名称,避免使用无意义或缩写的名称。例如,使用 number_of_students 而不是 nos

语句

选择语句

在C语言中,选择语句用于根据条件执行不同的代码块。C语言提供了两种选择语句:if语句和switch语句。

if语句

if语句的语法如下:

if (condition) {
    // 如果条件为真,执行这里的代码
} else {
    // 如果条件为假,执行这里的代码
}
  • 其中,condition是一个条件表达式,如果这个表达式的值为真(非0),则执行if语句后面花括号中的代码块,否则执行else语句后面花括号中的代码块(如果有的话)。else语句是可选的,如果没有指定,则条件为假时不执行任何代码。
int a = 10;
if (a > 0) {
    printf("a是正数\n");
} else {
    printf("a是非正数\n");
}

switch语句

switch语句的语法如下:

switch (expression) {
    case value1:
        // 如果expression等于value1,执行这里的代码
        break;
    case value2:
        // 如果expression等于value2,执行这里的代码
        break;
    // ... 可以有多个case分支
    default:
        // 如果expression和所有case的值都不匹配,执行这里的代码
        break;
}
  • 其中,expression是一个表达式,case value是一个常量表达式,表示当expression的值等于value时,执行后面花括号中的代码块。default是可选的,表示当expression的值和所有case的值都不匹配时,执行后面花括号中的代码块。
int a = 1;
switch (a) {
    case 1:
        printf("a等于1\n");
        break;
    case 2:
        printf("a等于2\n");
        break;
    default:
        printf("a不等于1也不等于2\n");
        break;
}

循环语句

循环语句用于重复执行一段代码,直到满足某个条件为止。C语言提供了3种循环语句:while循环、do-while循环和for循环。

while循环:

while循环的语法如下:

while (condition) {
    // 只要条件为真,就一直执行这里的代码
}
  • 其中,condition是一个条件表达式,只要这个表达式的值为真(非0),就会一直执行while循环后面花括号中的代码块。
int i = 0;
while (i < 10) {
    printf("%d\n", i);
    i++;
}

do-while循环:

do-while循环的语法如下:

do {
    // 先执行一遍这里的代码
} while (condition);
  • 其中,condition是一个条件表达式,只要这个表达式的值为真(非0),就会继续执行do-while循环后面花括号中的代码块。do-while循环保证会至少执行一次循环体中的代码。
int i = 0;
do {
    printf("%d\n", i);
    i++;
} while (i < 10);

for循环:

for循环的语法如下:

for (initialization; condition; update) {
    // 只要条件为真,就一直执行这里的代码
}
  • 其中,initialization是循环变量的初始值;condition是一个条件表达式,只要这个表达式的值为真(非0),就会继续执行for循环后面花括号中的代码块;update是循环变量的更新操作,用于控制循环变量的变化。
for (int i = 0; i < 10; i++) {
    printf("%d\n", i);
}

跳转语句

跳转语句用于控制程序的执行流程,可以跳过某些语句、重复执行某些语句或者跳转到程序的其他位置。C语言中提供了3种跳转语句:break语句、continue语句和goto语句。

break语句:

  • break语句用于跳出循环语句(for循环、while循环、do-while循环或switch语句),并继续执行循环语句后面的代码。
for (int i = 0; i < 10; i++) {
    if (i == 5) {
        break;//只要打印到5就跳出循环
    }
    printf("%d\n", i);
}

continue语句:

  • continue语句用于跳过循环语句中的某些语句,继续执行下一次循环。
for (int i = 0; i < 10; i++) {
    if (i == 5) {
        continue;//打印到5时跳过本次循环,继续打印6、7、8、9
    }
    printf("%d\n", i);
}

goto语句:

  • goto语句用于跳转到程序的其他位置,可以用于实现复杂的控制流程。
  • 但由于goto语句容易导致程序的可读性和可维护性变差,因此应该避免过度使用。
int i = 0;
loop:
    printf("%d\n", i);
    i++;
    if (i < 10) {
        goto loop;
    }

函数

  • 在C语言中,函数是一段封装了特定功能的代码块,它可以通过函数名和参数列表进行调用。

  • 函数可以帮助我们将程序分解成小的、可重用的部分,提高代码的可读性、可维护性和可重用性。

  • C语言中的函数通常包括以下几个部分:函数声明、函数定义、函数调用

函数声明

  • 函数声明是告诉编译器函数的名字、返回类型和参数列表等信息,以便在函数被调用时进行类型检查和参数匹配。
  • 函数声明通常放在源文件的开头或头文件中。

函数声明的语法如下:

返回类型 函数名(参数列表);
  • 其中,返回类型表示函数的返回值类型,函数名是一个标识符,用于唯一标识函数,参数列表是一组用逗号分隔的参数类型和参数名。
int max(int a, int b);

函数定义

  • 函数定义是实现函数功能的实际代码,包括函数名、参数列表、返回类型和函数体等部分。函数定义通常放在源文件中。

函数定义的语法如下:

返回类型 函数名(参数列表) {
    // 函数体
}

其中,返回类型、函数名和参数列表与函数声明相同,函数体是一段实现函数功能的代码块。

int max(int a, int b) {//这个函数定义实现了找出两个整数中的最大值功能。
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

函数调用

  • 函数调用是使用函数名和参数列表来执行函数代码的过程。在函数调用时,需要提供与函数声明或定义中参数列表匹配的参数值。

函数调用的语法如下:

函数名(参数列表);
int a = 10, b = 20;
int max_value = max(a, b);//使用max函数来找出a和b中的最大值,并将结果赋值给max_value变量。
  • C语言中的函数可以有返回值,也可以没有返回值。如果函数没有返回值,则返回类型为void。如果函数有返回值,则需要使用return语句来返回一个值。
  • 函数可以有多个参数,参数之间使用逗号分隔。
  • 如果函数没有参数,则参数列表可以为空,但是圆括号不能省略。
#include<stdio.h>  
//函数
// 函数声明
int add(int a,int b);
// 函数定义
int add(int a,int b)
{
	return a + b;
 } ;
 
int main()
{
//	函数调用
	int a = 10, b = 20;
	int res = add(a, b);
	printf("%d\n",res);
	
	return 0;
}

数组

  • 在C语言中,数组是一种存储相同类型数据的集合,它们按照一定的顺序排列,并可以通过下标来访问其中的元素。数组可以是一维数组、二维数组、多维数组等。
  • 在C语言中,数组是一种非常常用的数据结构,它可以用于存储和处理大量的数据,并可以通过循环等方式进行高效的遍历和操作。
  • 但是,数组的大小在编译时就已经确定,因此它的大小不能动态地改变。
  • 如果需要动态地增加或减少数组的大小,可以考虑使用动态分配内存的方式,例如使用malloc函数来动态分配数组内存空间。

定义

C语言中的数组定义需要指定数组的类型、名称和元素个数

int a[10];   // 定义一个包含10个int类型元素的数组a

访问

下标访问

  • 数组的元素可以通过下标访问
a[0] = 1;   // 给数组第一个元素赋值为1
int x = a[1];   // 从数组中获取第二个元素的值
  • 数组的下标可以是任何整数类型,包括正整数、负整数和0。

  • 如果下标超出了数组的索引范围,则可能会导致运行时错误,例如访问未定义的内存地址。因此,在使用数组时需要特别注意下标的取值范围。

  • C语言中的数组也可以使用初始化列表来初始化数组元素的值

int a[5] = {1, 2, 3, 4, 5};   // 定义一个包含5个int类型元素的数组a,并初始化为1、2、3、4、5

指针操作

除了循环以外,C语言中还有一些其他的方式可以高效地遍历和操作数组,包括指针、函数指针、指针算术等。

  1. 指针
  • 指针是C语言中的一种特殊数据类型,它保存了一个变量的内存地址。
  • 在使用指针操作数组时,可以通过指针访问数组中的元素,例如:
int a[5] = {1, 2, 3, 4, 5};
int *p = a;   // 将数组a的首地址赋值给指针p
int x = *(p + 1);   // 通过指针p访问数组中的第二个元素(即a[1])

这个例子定义了一个名为a的数组,包含5个int类型的元素,然后将数组的首地址赋值给指针p。通过指针p可以访问数组中的元素,例如获取第二个元素的值。

  1. 函数指针
  • 函数指针是指向函数的指针变量,它可以存储函数的地址,并且可以作为参数传递给其他函数或作为返回值返回给调用者。
  • 在使用函数指针操作数组时,可以将指针指向一个函数,然后通过指针调用该函数来遍历和操作数组,例如:
void process(int *p, int n, void (*func)(int *)) {
//定义了一个名为process的函数,它接受一个指向数组的指针、数组的长度和一个函数指针作为参数
    for (int i = 0; i < n; i++) {
        func(p + i);
    }
}

void print(int *p) {
    printf("%d ", *p);
}

int a[5] = {1, 2, 3, 4, 5};
process(a, 5, print);   // 使用函数指针print遍历数组a并打印数组元素
  1. 指针算术
  • 指针算术是指对指针进行加、减、自增、自减等操作的过程。
  • 在使用指针算术操作数组时,可以使用指针进行遍历和操作,例如:
int a[5] = {1, 2, 3, 4, 5};
int *p = a;   // 将数组a的首地址赋值给指针p
for (int i = 0; i < 5; i++) {
    printf("%d ", *p);   // 打印指针p指向的数组元素的值
    p++;   // 将指针p向后移动一个元素
}

需要注意的是,在使用指针操作数组时,需要特别注意指针的取值范围和指针算术的正确性,否则可能会导致未定义的行为或运行时错误。

操作符

  • 在C语言中,有很多常用的操作符,包括算术操作符、关系操作符、逻辑操作符、位操作符、赋值操作符、条件操作符、指针操作符等。

下面是常用的一些操作符的介绍:

算术操作符

算术操作符用于执行数学运算,包括加、减、乘、除、取模等。常用的算术操作符包括:

  • 加法操作符:+
  • 减法操作符:-
  • 乘法操作符:*
  • 除法操作符:/
  • 取模操作符:%

例如,下面的代码演示了如何使用算术操作符进行加、乘、取模运算:

int a = 10, b = 3;
int c = a + b;   // c的值为13
int d = a * b;   // d的值为30
int e = a % b;   // e的值为1

关系操作符

关系操作符用于比较两个值的大小或关系,返回值为真(非0)或假(0)。常用的关系操作符包括:

  • 等于操作符:==
  • 不等于操作符:!=
  • 大于操作符:>
  • 小于操作符:<
  • 大于等于操作符:>=
  • 小于等于操作符:<=

例如,下面的代码演示了如何使用关系操作符进行大小比较:

int a = 10, b = 3;
int c = a > b;   // c的值为1,表示a大于b
int d = a < b;   // d的值为0,表示a小于b
int e = a == b;  // e的值为0,表示a等于b

逻辑操作符

逻辑操作符用于执行逻辑运算,包括与、或、非等。常用的逻辑操作符包括:

  • 逻辑与操作符:&&
  • 逻辑或操作符:||
  • 逻辑非操作符:!

例如,下面的代码演示了如何使用逻辑操作符进行逻辑运算:

int a = 10, b = 3, c = 0;
int d = (a > b) && (c == 0);   // d的值为1,表示a大于b并且c等于0
int e = (a < b) || (c != 0);   // e的值为1,表示a小于b或者c不等于0
int f = !(a > b);             // f的值为0,表示a不大于b

位操作符

位操作符用于对二进制位进行操作,包括按位与、按位或、按位异或等。常用的位操作符包括:

  • 按位与操作符:&
  • 按位或操作符:|
  • 按位异或操作符:^
  • 按位取反操作符:~

例如,下面的代码演示了如何使用位操作符进行位运算:

int a = 0b1010, b = 0b1100;
int c = a & b;   // c的值为0b1000,表示a和b按位与的结果
int d = a | b;   // d的值为0b1110,表示a和b按位或的结果
int e = a ^ b;   // e的值为0b0110,表示a和b按位异或的结果
int f = ~a;      // f的值为0b0101,表示a按位取反的结果

赋值操作符

赋值操作符用于将一个值赋给一个变量或表达式。常用的赋值操作符包括:

  • 等于操作符:=
  • 加等于操作符:+=
  • 减等于操作符:-=
  • 乘等于操作符:*=
  • 除等于操作符:/=
  • 取模等于操作符:%=

例如,下面的代码演示了如何使用赋值操作符进行赋值运算:

int a = 10, b = 3;
a += b;   // 将a加上b的值,并将结果赋给a
a *= b;   // 将a乘以b的值,并将结果赋给a
a %= b;   // 将a对b取模的结果赋给a

条件操作符

  • 条件操作符也称为三元操作符,它是C语言中唯一的一个三元操作符,用于在两个值之间选择一个值。常用的条件操作符包括:

  • 条件操作符:exp1 ? exp2 : exp3

例如,下面的代码演示了如何使用条件操作符进行条件选择:

int a = 10, b = 3;
int max = (a > b) ? a : b;   // 如果a大于b,则将a赋给max,否则将b赋给max

指针操作符

  • 指针操作符用于对指针进行操作,包括取地址、取值等。
  • 常用的指针操作符包括:
    • 取地址操作符:&
    • 取值操作符:*
    • 自增操作符:++
    • 自减操作符:--

例如,下面的代码演示了如何使用指针操作符进行指针操作:

int a = 10;
int *p = &a;     // 取变量a的地址,并将地址赋给指针p
int b = *p;      // 取指针p指向的变量的值,并将值赋给变量b
int *q = p++;    // 将指针p向后移动一个位置,并将移动前的地址赋给指针q
int *r = --p;    // 将指针p向前移动一个位置,并将移动后的地址赋给指针r

常见关键字

在C语言中,关键字是具有特殊含义的保留字,用于表示程序的结构、控制流、数据类型等。下面是C语言中常用的关键字:

数据类型关键字

C语言中的数据类型关键字用于定义变量的数据类型,包括:

  • int:整型
  • char:字符型
  • float:单精度浮点型
  • double:双精度浮点型
  • void:无类型

例如,下面的代码定义了一个整型变量和一个字符型变量:

int age = 20;
char name = 'John';

流程控制关键字

C语言中的流程控制关键字用于控制程序的流程,包括:

  • if、else:条件语句
  • switch、case:多分支语句
  • while、do、for:循环语句
  • break、continue:跳转语句

例如,下面的代码使用了if语句和for循环语句:

int i;
for (i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        printf("%d is even\n", i);
    } else {
        printf("%d is odd\n", i);
    }
}

函数关键字

C语言中的函数关键字用于声明和定义函数,包括:

  • return:返回语句
  • int、char、float、double、void:函数返回值类型
  • main:程序入口函数

例如,下面的代码定义了一个返回整型值的函数:

int add(int a, int b) {
    return a + b;
}

存储类型关键字

C语言中的存储类型关键字用于指定变量的存储类型,包括:

  • auto:自动变量
  • static:静态变量
  • extern:外部变量
  • register:寄存器变量

例如,下面的代码定义了一个静态变量和一个外部变量:

static int count = 0;
extern int sum;

指针关键字

C语言中的指针关键字用于声明和操作指针,包括:

  • *:指针声明符号
  • &:取地址运算符

例如,下面的代码定义了一个指向整型变量的指针:

int a = 10;
int *p = &a;

define定义常量和宏

  • 在C语言中,define是用来定义常量和宏的预处理指令,它可以在程序编译之前将代码中的宏和常量替换为指定的值,从而提高程序的效率和可维护性。

定义常量

  • 使用define可以定义一个常量,常量的值在程序执行过程中不能被改变。

定义常量的语法如下:

#define 常量名 值

例如,下面的代码定义了一个名为PI的常量,它的值为3.14:

#define PI 3.14
  • 在程序中使用常量时,可以直接使用常量名,编译器会将常量名替换为它的值。例如:
double r = 1.0;
double area = PI * r * r;

定义宏

  • 使用define可以定义一个宏,宏是一段代码片段,可以在程序中多次使用。

定义宏的语法如下:

#define 宏名 替换文本
  • 替换文本可以是一段代码,可以包含变量、运算符、控制语句等。
#define MAX(a, b) ((a) > (b) ? (a) : (b))
//定义了一个名为MAX的宏,它返回两个数中的最大值
  • 在程序中使用宏时,可以将宏名作为函数调用的方式使用,编译器会将宏名替换为它的替换文本。例如:
int a = 10, b = 20;
int max = MAX(a, b);
//在这个例子中,MAX被替换为它的替换文本((a) > (b) ? (a) : (b)),最终计算出a和b中的最大值。
  • 需要注意的是,使用宏可能会带来一些副作用,例如替换文本中的变量可能会被重复计算、宏定义中的参数不一定会进行类型检查等。因此,在使用宏时需要注意一些细节,以避免出现问题。

指针

  • 在C语言中,指针是一种特殊的变量,它存储了一个内存地址,这个地址指向计算机内存中的某个位置,可以用来访问和修改该位置的数据。
  • 指针在C语言中是非常重要的概念之一,它可以用来实现动态内存分配、数组和字符串的操作、函数的传递等。需要掌握指针的定义、赋值、访问、算术运算等操作。

指针的定义和使用可以分为以下几个方面:

指针的定义

  • 在C语言中,可以使用指针类型来定义一个指针变量,指针类型的语法如下:
数据类型 *指针变量名;
  • 其中,数据类型表示指针所指向的数据类型,指针变量名是指针变量的名称,*表示指针类型。
int *p;//定义一个整型指针变量p
  • 在定义指针变量时,需要注意指针变量所指向的数据类型,指针变量只能指向与其类型相同的变量或数据类型。

指针的赋值和访问

  • 指针变量存储的是一个内存地址,可以通过赋值操作将其指向一个具体的内存位置。指针变量的赋值语法如下:
指针变量名 = &变量名;
  • 其中,&表示取地址运算符,可以获取变量在内存中的地址。
int a = 10;
int *p = &a;//将指针变量p指向了整型变量a的地址:
  • 指针变量可以通过解引用操作(*)来访问指针所指向的内存位置中的数据。
int a = 10;
int *p = &a;//通过指针变量p来访问a的值
//*p表示指针所指向的内存位置中存储的数据,在这里就是a的值。
printf("a = %d\n", *p);

指针的算术运算

  • 指针还支持一些算术运算,可以对指针进行加、减、比较等操作。这些算术运算可以用来实现数组、字符串等数据结构的操作。

例如,可以将指针加上一个整数n来访问指针所指向内存位置中的下一个或上一个元素:

int a[5] = {1, 2, 3, 4, 5};
int *p = a;
printf("%d\n", *(p + 1)); // 访问a[1]的值
//在这个例子中,p表示指向数组a的第一个元素的指针,可以使用p + 1来访问a[1]的值。

指针的空指针和野指针

  • 空指针是指未被初始化的指针,它的值为NULL。
  • 野指针是指指针变量指向的内存位置没有被分配或已经被释放,使用野指针可能会导致程序崩溃或数据损坏

结构体

  • 在C语言中,结构体是一种自定义数据类型,它可以将多个不同类型的数据组合在一起,形成一个新的复合数据类型。结构体在C语言中被广泛使用,可以用来表示复杂数据结构、数据记录、对象等。
  • 结构体在C语言中被广泛使用,需要掌握结构体的定义、声明、初始化、指针和嵌套等操作。

结构体的定义和使用可以分为以下几个方面:

结构体的定义

  • 在C语言中,可以使用关键字struct来定义一个结构体类型,结构体类型的语法如下:
struct 结构体名 {
    数据类型 成员1;
    数据类型 成员2;
    // ...
};

其中,结构体名是结构体类型的名称,成员1、成员2等是结构体的成员变量,数据类型可以是任意合法的C语言数据类型。

struct Student {//定义一个名为Student的结构体类型,它有两个成员变量name和age
    char name[20];
    int age;
};

结构体的声明和初始化

  • 定义了结构体类型之后,可以声明结构体变量,并对其进行初始化。结构体变量的声明和初始化语法如下:
struct 结构体名 变量名 = {成员1的初始值, 成员2的初始值, ...};

下面的代码声明了一个名为s的结构体变量,并对其进行了初始化:

struct Student s = {"Tom", 20};
  • 在程序中使用结构体变量时,可以使用点操作符(.)来访问结构体的成员变量。

例如,下面的代码输出了结构体变量s的成员变量name和age:

printf("name: %s, age: %d\n", s.name, s.age);

结构体的指针

  • 结构体变量可以使用指针来进行访问和修改。使用结构体指针的语法如下:
struct 结构体名 *指针变量名;
struct Student *p = &s;//定义一个指向Student结构体的指针变量p,并将它指向结构体变量s的地址:
  • 指针变量可以使用箭头操作符(->)来访问结构体成员变量。
printf("name: %s, age: %d\n", p->name, p->age);//下面的代码输出了指针变量p所指向的结构体变量的成员变量name和age

结构体的嵌套

  • 结构体可以嵌套在其他结构体中,形成更复杂的数据类型。
struct Course {
//定义了一个名为Course的结构体类型,它包含了一个Student结构体类型的成员变量student和一个整型成员变量score
    struct Student student;
    int score;
};
  • 在程序中使用嵌套结构体时,可以使用点操作符或箭头操作符来访问结构体的成员变量。
struct Course c = {{"Tom", 20}, 90};
printf("name: %s, age: %d\n", c.student.name, c.student.age);
//输出了嵌套结构体变量c的成员变量student的成员变量name和age
posted @ 2023-07-23 00:22  FL不凡  阅读(76)  评论(0编辑  收藏  举报