c语言 面试前必备基础知识

c语言 数组指针/c语言 指针数组

c语言 数据类型

c语言 数据类型的转换优先级: char-->float-->short-->int-->double

char //字符数据类型 1个字节
short int //短整型 2个字节 [int 可以省略]
int //整形 4个字节
long int //长整型 32位OS 4个字节(64位OS 8个字节) [int 可以省略]
long long int //更长的整形 8个字节 [int 可以省略]
float //单精度浮点数 4个字节 eg:定义一个 float 型变量 float x = 3.4f (如果不加f,计算机默认为双精度浮点数)
double //双精度浮点数 8个字节 eg:定义一个 double 型变量 double y = 9.79
整数后加u或U 明确说明为无符号整型数 eg 38u
整数后加l或L 明确说明为长整型数 eg 38L
38lu:无符号长整形数

有了以下知识,就可以理解上述数据类型的字节了。

1、c语言规定了存储 0 或 1 的最小单位叫做比特 bit

2、c语言规又定了 1 个字节 (byte) 为8个 bit。

那么这里我们就明白了:为什么64位的操作系统存储"long类型"需要64/8=8个字节 ;32位的OS存储"long类型"需要32/8=4个字节

3、我们知道计算机只认识 0,1 两种数字(0代表负电,1代表正电),所以只能存储 0 或 1。即64位操作系统(OS)中的每一位有2种存储选择,可以存放0或 1。那么总共就有了2^64 种存储方案

二进制十进制
00000
00011
00102
00113
01004
01015
64个12^64-1

c语言 数据类型打印格式 %c %s %d %f %lf %p %x %o %lu %lld

%c		打印字符类型
%s		打印字符串类型
%d		打印整形
%f		打印单精度浮点型(float)
%lf 	打印双精度浮点型(double)
%p		以地址的形式打印
%x      打印16进制数
%o		打印8进制数
%lu		long int 简写[long]
%lld	    long long int	简写[long long]

在这里插入图片描述

小练习1

1、下面程序的输出正确的是__。

#include<stdio.h>

void main()
{
	int k = 11;
	printf("k=%d,k=%o,k=%x\n", k, k, k);
}
A) k=11,k=12,k=11           B) k=11,k=13,k=13
C) k=11,k=013,k=0xb         D) k=11,k=13,k=b

答案:D

c语言 格式化输出

注意:格式化输出涉及太多零碎知识,这里我们只给出常用的格式化。

%md

使不足m位的int型变量以m位进行右对齐输出,高位用空格补齐。如果本身超过m位,则保持原样

#include<stdio.h>

int main(){
	int a = 123, b = 1234567;
	printf("%2d\n", a);
	printf("%5d\n", a);
	printf("%5d\n", b);
	return 0;
} 

在这里插入图片描述

%0md

当变量不足m位时,在前面补0

#include<stdio.h>

int main(){
	int a = 123, b = 1234567;
	printf("%05d\n", a);
	printf("%05d\n", b);
	return 0;
}

在这里插入图片描述

%m.nf
#include <stdio.h>

int main() {
    float y = 12.345;
    // %m.nf:m为指定的输出字段的宽度,n为小数点后保留n位

    printf("x=%5.2f\n", y); // 输出结果:x=12.35
    /*
    解释:
        1. n为2,则小数点后保留2位,故【.34】
        2. m为5,字段宽度为5,向前在补2位,故【12.34】(小数点也占字段宽度)
        3. 由于四舍五入,故【12.35】

    */
    return 0;
}

必看

#include <stdio.h>

int main() {
    float y = 12.345;
    // %m.nf:m为指定的输出字段的宽度,n为小数点后保留n位

    printf("x=%0.2f\n", y); // 输出结果:x=12.35
    printf("x=%1.2f\n", y); // 输出结果:x=12.35
    printf("x=%2.2f\n", y); // 输出结果:x=12.35
    printf("x=%3.2f\n", y); // 输出结果:x=12.35
    printf("x=%4.2f\n", y); // 输出结果:x=12.35
    printf("x=%5.2f\n", y); // 输出结果:x=12.35
    printf("x=%6.2f\n", y); // 输出结果:x= 12.35 注意有空格
    /*
    解释:
        1. n为2,则小数点后保留2位,故【.34】
        2. 由于四舍五入,故【.35】
        3. 由于编译器需要保证这个整数的实际意义,所以它会自动把整数部分补齐。故【.35】(只要字段宽度<=5,即m<=5)
        4. 当m>5时,如m=6,加上整数部分,字段长度不足6位,所以最左端用空格补齐
        5. 当m=7时,最左端补2个空格,依此类推

    */
    return 0;
}

小练习1

#include<stdio.h>

int main()
{
	int a = 2008, b = 8;
	float f = 1.1;
	double d = 1.21;
	float x = 361.568, y = -123.456;
	char ilc[] = { "I love China!" }; //字符串长度为13
	printf("%f\n",f);//输出结果为:1.100000
	printf("%lf\n",d);//输出结果为:1.210000
	printf("%2d,%2d\n", a, b); //输出结果为:2008, 空格8
	printf("%8.3f-%8.3f=%8.2f\n", x, y, x-y);//输出结果为:空格361.568--123.456=空格空格485.02
	printf("%16s\n", ilc);//输出结果为:空格空格I love China!
	printf("%5s\n", ilc);//输出结果为:I love China!
	return 0;
}

在这里插入图片描述

c语言 常用字符的ASCII值

字符ASCII值
A65
a97
空格32
换行10
数字048
数字149

c语言 变量 常量

化分依据:值是否会变化

c语言 变量
c语言 变量命名规范

(1)只能由字母、数字、下划线构成

(2)开头只能由字母、下划线构成

(3)关键字不能作为标识符

c语言 变量存储类型 auto static extern register

自动(auto)、静态(static)、外部(extern)、寄存器 (register)

这些存储类型的具体意义

c语言:局部变量 全局变量

c语言根据变量作用域将变量分为:局部变量 全局变量

人话:是否在大括号{}的内部或外部, 在{}内:叫做局部变量

注意:C语言语法规定,变量要定义在当前代码块的最前面

#include<stdio.h>

int num1 = 77; //全局变量定义在大括号{}外
int main()
{
	int num2 = 99; //局部变量定义在大括号{}内
	{
		int num = 100; //局部变量定义在大括号{}内
	}
	//以下可以写业务逻辑代码(变量必须定义在业务逻辑代码的上边)
	return 0;
}
c语言 常量

C语言中的常量分为以下以下几种:

  1. 整形常量

  2. 浮点常量

  3. 字符常量

  4. 字符串常量

  5. 枚举常量

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

// 枚举关键字 enum
enum Sex {
	MALE, // 枚举常量
	FEMALE // 枚举常量
};

int main()
{
	//打印枚举常量的初始值
	printf("%d\n", MALE);
	printf("%d\n", FEMALE);
	return 0;
}

在这里插入图片描述

c语言 字符串

  • 常见字符串定义的两种方式

在这里插入图片描述

  • 常见字符串函数

我们知道,字符串的结束标志为 \0,那么可以做一下以下题目

1. strlen

该函数不会返回负数

#define _CRT_SECURE_NO_WARNINGS 1

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

// 判读字段串的长度
int main()
{
	char arr1[] = { 'a', 'b', 'c',0 };
	char arr2[] = { 'a', 'b', 'c','\0' };
	char arr3[] = { 'a', 'b' };
	printf("%d\n", strlen(arr1));
	printf("%d\n", strlen(arr2));
	printf("%d\n", strlen(arr3));
	return 0;
}

在这里插入图片描述

解释:

1、arr3,没有字符串结束标志,所以abc后边跟的是随机值,统计的是 abc + 随机值的长度

2、arr2,有字符串结束,所以统计的是 abc 的长度

3、我们知道计算机是不认识字母和某些数字的(除了 1 or 0外)。那么计算机存储字母 a 时,就必须转换为 0 或 1。所以国际语言标准就为每个字母,数字,或符号都赋了一个特定的数值,例如 a 为 97,然后计算机就可以将十进制的 97 转换为了二进制的 1100001。那么同理,字符串结束标志 \0 也有一个特定的值 0,那么c语言编译器扫描到 0 时,会认为是字符串的结束标志。看到这里我们就能明白 arr1 长度也是 3 了。

转义字符 \0 十进制值为 0

字符 0 十进制值为 48

2. strcpy

字符串拷贝函数

  • 源字符串必须以’\0’结束。
  • 会将源字符串中的’\0’拷贝到目标空间。
#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "xyz";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 目标空间必须足够大,以确保能存放源字符串。目标空间必须可变。
#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "abcdef"; 
	char arr2[] = "xyz"; // arr2空间必须足够大
	strcpy(arr2, arr1); // 错误写法 arr2空间不足
	return 0;
}
3. strcat

字符串追加函数

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

int main()
{
	char arr1[44] = "abcdef"; // arr1空间必须足够大
	char arr2[] = "xyz";
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	return 0;
}

在这里插入图片描述

4. strcmp

字符串比较函数

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

int main()
{
	char *p1 = "awbc";
	char *p2 = "abyz"; // 比较规则:a和a比较 w和b进行比较,b和y进行比较,依次类推
	printf("%d\n", strcmp(p1, p2)); // p1>p2 返回大于0的数 p1=p2 返回0 p1<p2 返回小于0的数 
	
	return 0;
}

在这里插入图片描述

5. strstr

查找字符串

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

int main()
{
	char *p1 = "abcdefabcdef";
	char *p2 = "def";
	char *ret = strstr(p1, p2);
	if(ret == NULL){
		printf("子串不存在!\n");
	}else{
		printf("%s\n",ret); // 若存在,返回第一次出现位置后的所有字符串
	}
	
	return 0;
}

在这里插入图片描述

c语言 转义字符

语句中只要有\就表示转义

问题: 小明多年前在电脑中的某个位置(C:\users\xxx.mp4)存了一部岛国电影,现在忘记了。所以请你把电影的存储路径打印给他

因为路径中有\,所以默认情况下会进行转义。若想把影片路径中的\打印出来,在加一个\,表示在转义
在这里插入图片描述

打印输出 单引号,双引号

在这里插入图片描述

c语言 操作符

1、算术操作符 + - * / %
+ - * / %

% 为求余运算符,该运算符只能对整型数据进行运算。且符号与被模数相同。5%2=1;5%-2=1;-5%2= -1;(-5)%(-2)= -1;

/ 为求商运算符,该运算符能够对整型、字符、浮点等类型的数据进行运算

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 5;
	//整除
	printf("%d\n", (a / 2));
	//取余
	printf("%d\n", (a % 2));
	return 0;
}

在这里插入图片描述

小练习2

在这里插入图片描述

(1)相同数据类型的元素进行数学运算(+、-、*、/)得到结果还保持原数据类型。

(2)不同数据类型的元素进行数学运算,先要统一数据类型,统一的标准是低精度类型转换为高精度的数据类型。

选项A,11与3为两个整形,11/3结果的数据类型也应为整形,因此将3.666666的小数部分全部舍掉,仅保留整数,因此11/3=3。

选项B,11.0为实型,3为整形,因此首先要统一数据类型,将整型数据3转换为3.0,转换后数据类型统一为实型数据,选项B变为11.0/3.0,结果的数据类型也应为实型数据,因此选项B11.0/3=3.666666。

选项C,先将整数11强制类型转换,转换为实型11.0,因此选项C变为11.0/3,其后计算过程、结果与选项B同。

2、移位操作符 >> <<
>> <<

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 5;
	//向左移动2位
	printf("%d\n", (a << 2));
	//向右移动2位
	printf("%d\n", (a >> 2));
	return 0;
}

在这里插入图片描述

3、位操作符 & ^ |
& ^ |

在这里插入图片描述

4、赋值操作符 = += -= *= /=
= += -= *= /= 

小练习1

8、设 int a=12,则执行完语句a+=a-=a*a后,a的值是___.
A) 552        B) 264      C) 144        D) -264

答案:D 从右到左,依次计算即可

  1. a*a=144
  2. a=a-144=-132
  3. a=a+(-132)=-264

小练习2

22、已知a=12,则表达式a+=a-=a*=a的结果是___.
A) 0         B) 144        C) 12        D) -264

答案:A 从右到左,依次计算即可

小练习3

以下答案正确的是___。
#include<stdio.h>

int main()
{
	int x = 10;
	x *= 3 + (x % 3);
	printf("%d\n", x);
	return 0;
}

A. 31 	B. 40

答案:B

  1. 赋值运算符的优先级最低
  2. x%3 = 1
  3. 3+1 =4
  4. x = 10*4
5、单目操作符
!           逻辑反操作
-           负值
+           正值
&           取地址
sizeof      操作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          --在前,先----在后,算完其它后,在--
++          
*           间接访问操作符(解引用操作符)
(类型)       强制类型转换
  • 前置++和后置++的区别
#include<stdio.h>

int main()
{
	int a = 1, b = 8,x,y;
	x = ++a; // ++在前,先++,在赋值给x x=2
	y = b++; // ++在后,先赋值给y,然后在++ y=8
	printf("%d\n",b); // 9
	return 0;
}

c语言中,除了数字0,其它一切非0值都为1。 eg: -7 ,7, 3.3, 4.42 类型的 都是 1

小练习1

小练习2

运算符号的优先级想要搞懂,必须做题,这里给一个小栗子

在这里插入图片描述
答案:B

  1. !x=0
  2. 0||y
  3. x=2
  4. y =0

在这里插入图片描述

小练习3

前置++
在这里插入图片描述
注意:这里的 ! 优先级 比前置 ++ 的低,先计算 ++x

  • 【*p++ |*(p++) | *++p | (*p)++ | ++(*p) 区别】

*p++:等同于:*p; p += 1;

#include<stdio.h>

int main() {
    char s[99] = {"hello"};
    char *q = s;
    while (*q++) {
        printf("%c", *q); 
    }
    return 0;
}

在这里插入图片描述

  1. while->先计算*p=h 然后再++
  2. while循环体内 再计算*p

错误理解:由于 * 和 ++ 的运算优先级一样,在优先级相同时,遵循自右向左结合的规则。p先与++结合,然后p++整体再与*结合

正确写法

#include<stdio.h>

int main() {
    char s[99] = {"hello"};
    char *q = s;
    while (*q) {
        printf("%c", *q); 
		q++;
	}
    return 0;
}

在这里插入图片描述

* p++ 与*(p++)无区别

#include<stdio.h>

int main() {
	// 拷贝str1中的defgh
	char str1[]={"abcdefgh"};
	char str2[99];
	char *p =str1+3,*q=str2,*t=str2;
	while(*p){
		*(q++)=*p++; // 这里可以证明2者无区别
		// 详细步骤:*q=*p; p++;q++;
	}
	*q='\0';
	printf("%s\n",t);

}

在这里插入图片描述

*++p:等同于 p += 1; *p;

(*p)++,使用()强制将*与p结合,只能先计算*p,然后对*p整体的值++

++(*p),先*p取值,再前置++,[该值+1后]作为整个表达式的值

7、关系操作符
>
>=
<
<=
!=      用于测试“不相等”
==      用于测试“相等”

小练习1

26、下面程序的输出结果是____.
#include<stdio.h>
void main()
{
  int a=5,b=3;
  float x=3.14, y=6.5;
  printf("%d,%d\n",a+b!=a-b,x<=(y-=6.1));
}

A) 1,0        B) 0,1      C) 1,1        D) 0,0

答案:A

  1. a+b=8
  2. a-b=2
  3. 8!=2
  4. y=y-6.1=0.4
  5. x<=0.4
8、逻辑操作符 && ||
&&     逻辑与 只有两个为真时,才为1
||     逻辑或 任意一个为真,才为1
真:除0以外所有的数都为真,包括负数,小数

必看
在这里插入图片描述
解释:&&的左边,只要为假,&&右边的优先级无论多高,计算机都不会在计算,直接返回0

小练习1

25、下面程序的输出结果是______.
#include<stdio.h>
void  main() 
{
 int a=-1, b=4, k;
 k=(++a<=0)&&(b--<=0);
 printf("%d,%d,%d\n",k,a,b);
}

A) 1,1,2      B) 1,0,3    C) 0,1,2      D) 0,0,3

答案:D

  1. ++a=0
  2. 0<=0
  3. b<=0 结果为0
  4. 1&&0 结果为0
  5. k=0
  6. b=3

c语言 原码、反码、补码

在这里插入图片描述

  1. 对于整形来说,计算机内存存储的是补码
  2. debug时,编译器呈现给我们的是16进制数据。

c语言 常见函数

  • scanf
#include<stdio.h>

int main()
{
	char ch;
	scanf("%3c", &ch);
	printf("%c", ch);
	return 0;
}
如果从键盘上输入
    abc<回车>
则程序的运行结果是___.
A) a        B) b        C) c    D) 程序语法出错

答案:A

解析:如果从键盘上连续输入3个字符abc,由于ch只能容纳一个字符,系统就把第一个字符‘a’赋给字符变量ch。3为指定的输入字段的宽度。如果数据的位数小于3,则等待直到满足3字符长度(如果有回车,则包含回车符),若大于3,则截断后输出前3字符。

  • getc 和putc

getc :从流中读取单个字符
putc :从流中输出单个字符
流:可以是 控制台(黑窗口cmd),也可以是文本文件等
在这里插入图片描述

  • getchar和putchar

getchar:读取用户从键盘输入的单个字符
putchar:向终端输出一个字符
在这里插入图片描述

  • fgetc和fputc

fetc:一次从文件流中读取一个字符
在这里插入图片描述
fputc:向文件流中一次写一个字符
在这里插入图片描述

  • gets 和puts

gets:从流中读取一行字符串 知道遇到换行,才停止读取
puts:简单来说是,输出字符串
在这里插入图片描述

  • fgets和fputs

fets: 从流中读取一行字符串
在这里插入图片描述

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

int main(){
	FILE *pf = fopen("e:\\input\\hello.txt","r");
	char str[55]={0};
	if(pf==NULL){ // 读文件出错时,控制台打印出错信息
		printf("%s\n",strerror(errno));
		return 0;
	}
	// 读文件 
	// 将从文件中读取到的一行字符串,暂时放到缓冲区,缓冲区大小为1024个字符
	fgets(str,1024,pf);
	printf("%s\n",str);
	//关闭文件
	fclose(pf);
	return 0;
}

在这里插入图片描述
fputs: 向文件中写入字符串

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

int main(){
	FILE *pf = fopen("e:\\input\\wold.txt","w");
	
	if(pf==NULL){ // 读文件出错时,控制台打印出错信息
		printf("%s\n",strerror(errno));
		return 0;
	}
	// 写文件 
	fputs("b b",pf);
	fputs("c c",pf);
	//关闭文件
	fclose(pf);
	return 0;
}

在这里插入图片描述

  • fprintf和fscanf

在这里插入图片描述

fprintf:本例向文件中格式化输出学生信息

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

typedef struct stu {
    int on;
    float height;
    char hobby[10];
} Stu;

int main() {
    Stu s = {10086, 1.78f, "sing"};
    FILE *pf = fopen("e:\\input\\info.txt", "w");

    if (pf == NULL) { // 文件出错时,控制台打印出错信息
        printf("%s\n", strerror(errno));
        return 0;
    }
    // 写文件 
    fprintf(pf, "%d %f %s", s.on, s.height, s.hobby);
    //关闭文件
    fclose(pf);
    return 0;
}

在这里插入图片描述
fscanf:本例从文件中格式化读取学生信息,并输出到控制台

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

typedef struct stu {
    int on;
    float height;
    char hobby[10];
} Stu;

int main() {
    Stu s = {0};
    FILE *pf = fopen("e:\\input\\info.txt", "r");

    if (pf == NULL) { // 文件出错时,控制台打印出错信息
        printf("%s\n", strerror(errno));
        return 0;
    }
    // 从文件中读取结构化数据 
    fscanf(pf, "%d %f %s", &s.on, &s.height, &s.hobby);
    printf("%d %f %s", s.on, s.height, s.hobby);
    //关闭文件
    fclose(pf);
    return 0;
}

在这里插入图片描述

  • sprintf和sscanf
#include <stdio.h>

typedef struct stu {
    int on;
    float height;
    char hobby[10];
} Stu;

int main() {
    Stu s1 = {10086, 175, "sing"};
    Stu s2 = {0};
    char buf[1024] = {0};

    // 把格式化数据存储到字符串
    sprintf(buf, "%d %f %s", s1.on, s1.height, s1.hobby);
    printf("%d %f %s\n", s1.on, s1.height, s1.hobby);

    printf("**************************\n");

    // 从字符串中读取格式化数据
    sscanf(buf, "%d %f %s", &s2.on, &s2.height, &s2.hobby);
    printf("%d %f %s\n", s2.on, s2.height, s2.hobby);

    return 0;
}

在这里插入图片描述

  • fwrite和fread

fwrite:将数据以二进制的形式写入文件

#include <stdio.h>

struct S {
    char name[20];
    int age;
    double score;
};

int main() {
    struct S s = {"老王", 22, 88.4};
    FILE *pf = fopen("e:\\input\\info.txt", "wb");
    if (pf == NULL) {
        return 0;
    }
    // 二进制的形式写文件
    //fwrite(被写进去元素的地址,单个元素的大小,要写进去多少个这样的元素,写到哪里去);
    fwrite(&s, sizeof(struct S), 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;

}

在这里插入图片描述
fread: 读取二进制文件

#include <stdio.h>

struct S {
    char name[20];
    int age;
    double score;
};

int main() {
    struct S b = {0};
    FILE *pf = fopen("e:\\input\\info.txt", "rb");
    if (pf == NULL) {
        return 0;
    }
    // 二进制的形式读文件
    //fread(读取到的数据被放在哪里,单个元素的大小,读取多少个这样的元素,从哪里读文件);
    fread(&b, sizeof(struct S), 1, pf);
    printf("%s %d %lf\n", b.name, b.age, b.score);
    fclose(pf);
    pf = NULL;
    return 0;

}

在这里插入图片描述

  • fseek

fseek:指定位置读写
在这里插入图片描述

#include <stdio.h>

int main() {
    FILE *pf = fopen("e:\\input\\hello.txt", "r");
    if (pf == NULL) {
        return 0;
    }
    // 1. 定位文件指针
    // fseek(从哪里读取文件,指针偏移几个字节,文件指针初始位置)
    fseek(pf, 4, SEEK_CUR);
    // 2. 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);

    fclose(pf);
    pf = NULL;
    return 0;

}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • feof

feof:该函数用来判断系统读取文件时,是否正常结束

系统读取文件完毕时,会返回EOF(-1)。但是我们无法知道,是正常读取完毕后,还是读取异常后,返回的EOF,所以我们要用feof函数进行判断,如果feof函数返回真,表示正常读取完毕

#include <stdio.h>

int main() {
    FILE *pf = fopen("e:\\input\\hello.txt", "r");
    if (pf == NULL) {
        return 0;
    }
    int ch = 0;
    while ((ch = fgetc(pf)) != EOF) {
        putchar(ch);
    }
    if (ferror(pf)) {
        printf("读取错误,非正常结束!\n");
    }
    if (feof(pf)) {
        printf("读取正常结束!\n");
    }
    fclose(pf);
    pf = NULL;
    return 0;

}

c语言 数组

c语言 一维数组

判读以下数组的声明是否正确:

int a[ ];

答案:错

解析:只有在对数组初始化(即赋值)的时候才可以省略数组的长度,即int a[] = {1, 2, 3}

c语言 数组名(arr) 和 &数组名(&arr) 的区别

在这里插入图片描述

相同点

都可以表示数组首元素的地址

不同点

1、arr + 1:表示向后移动一个元素,即4个字节(移动一个int类型)

2、&arr + 1: 表示向后移动整个数组的长度,即40个字节

c语言 二维数组

1、二维数组的一维大小,即指二维数组的行数

2、一维数组初始化时可以省略数组长度

3、二维数组初始化时可以省略行数,但不能省略列数

# 判读题
A. int a[][]={1,2,3,4,5,6};(错,不能省略列数)
B. int a[2][]={1,2,3,4,5,6};(错,不能省略列数)
C. int a[][3]={1,2,3,4,5,6};()

c语言 结构体

c语言 简单结构体 定义 初始化 访问

#include<stdio.h>
/*
struct是自定义结构体类型的关键字
struct student 是用户定义的结构体类型
num,name,score都是结构体成员名
stu1是声明的全局变量(不推荐使用)也是结构体类型名
stu2是声明的局部变量
*/

struct student
{
	int num;//结构体成员名
	char name[10];//结构体成员名
	float score;//结构体成员名
}stu1;  // 全局变量 


int main()
{
	// 局部变量初始化
	struct student stu2 = { 86,"lisi" ,66 }; // stu2 局部变量
	printf("%d\n", stu2.num); //输出结果86
	return 0;
}

问题1,全局变量怎么赋初值?

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
/*
struct是结构体类型的关键字
struct student 是用户定义的结构体类型
num,score都是结构体成员名
stu1是声明的全局变量(不推荐使用)
stu2是声明的局部变量
*/

struct student
{
	int num;//结构体成员名
	char name[10];//结构体成员名
	float score;//结构体成员名
}stu1 = { 87,"zhangsan" ,55 };  // 全局变量


int main()
{
	struct student stu2 = { 87,"lisi" ,66 }; // stu2 局部变量
	return 0;
}
c语言 typedef关键字

问题2:可以把 用户定义的结构体类型 struct student,用简洁的形式代替吗?

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

// typedef:自定义类型关键字
typedef struct student
{
	int num;//结构体成员名
	char name[10];//结构体成员名
	float score;//结构体成员名
}Stu; // 自定义的类型(相当于域名)


int main()
{
	//用自定义的类型声明一个局部变量
	Stu stu2 = { 88,"wangwu" ,77 };
	return 0;
}
c语言 复杂结构体 初始化 访问

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

struct S
{
	int a;
	char c;
	char arr[20];
	double d;
};

struct T
{
	char ch[10];
	struct S s;
	char* pc;
};


int main()
{
	char arr1[] = "hello c";
	struct T t = { "hihi",{100, 'w',"hello world",3.14}, arr1 };
	printf("%s\n", t.ch); // hihi
	printf("%s\n", t.s.arr); // hello world
	printf("%lf\n", t.s.d); // 3.140000
	return 0;
}
c语言 匿名结构体类型

省略了结构体类型

struct
{
    int a;
    char b;
    float c;
}x;
c语言 结构的自引用 链表
struct Node
{
    int data; // 数据域
    // eg:一个节点想要找到另一个节点,可以存另一个节点的地址。那么要存储存储地址就需要指针,且这个指针类型需要和下一个节点的类型一致。
    struct Node* next; // 指针域 
};

使用typedef关键字

可以看以上 c语言 typedef关键字

typedef struct Node1
{
    int data;
    struct Node1* next;
}Node;
c语言 结构体内存对齐

即计算结构体的大小 这里我用的编译器 vs2019

c语言 结构体的对齐规则

1、第一个结构体成员距离结构体变量偏移量为0的地址处对齐。

2、其他结构体成员成员要对齐到,某个对齐数的整数倍处

对齐数 = 编译器默认对齐数 与 该结构体成员大小 的较小值

vs中默认的对齐数为8

linux中默认对齐数为4

3.、结构体总大小为最大对齐数(每个结构体成员都有一个对齐数)的整数倍。

4、如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

#include <stdio.h>

struct S1
{
	char c1;
	int i;
	char c2;
};

int main() {
	// 初始化
	struct S1 s1 = { 0 };
	printf("%d\n", sizeof(struct S1)); // 12

	return 0;
}

在这里插入图片描述

struct S3
{
    double d;
    char c;
    int i;
};

在这里插入图片描述

struct S4
{
    char c1;
    struct S3 s3;
    double d;
};

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值