目录
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 种存储方案
。
二进制 | 十进制 |
---|---|
0000 | 0 |
0001 | 1 |
0010 | 2 |
0011 | 3 |
0100 | 4 |
0101 | 5 |
… | … |
64个1 | 2^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值 |
---|---|
A | 65 |
a | 97 |
空格 | 32 |
换行 | 10 |
数字0 | 48 |
数字1 | 49 |
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语言中的常量分为以下以下几种:
-
整形常量
-
浮点常量
-
字符常量
-
字符串常量
-
枚举常量
#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
从右到左,依次计算即可
- a*a=144
- a=a-144=-132
- 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
- 赋值运算符的优先级最低
- x%3 = 1
- 3+1 =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
- !x=0
- 0||y
- x=2
- y =0
小练习3
前置++
注意:这里的 ! 优先级 比前置 ++ 的低,先计算 ++x
*p++:等同于:*p; p += 1;
#include<stdio.h>
int main() {
char s[99] = {"hello"};
char *q = s;
while (*q++) {
printf("%c", *q);
}
return 0;
}
- while->先计算*p=h 然后再++
- 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
- a+b=8
- a-b=2
- 8!=2
- y=y-6.1=0.4
- 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
- ++a=0
- 0<=0
- b<=0 结果为0
- 1&&0 结果为0
- k=0
- b=3
c语言 原码、反码、补码
- 对于
整形
来说,计算机内存存储的是补码
。 - debug时,编译器呈现给我们的是
16进制数据。
c语言 常见函数
#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 :
从流中输出单个字符
流:
可以是 控制台(黑窗口cmd),也可以是文本文件等
getchar:
读取用户从键盘输入的单个字符
putchar:
向终端输出一个字符
fetc:
一次从文件流中读取一个字符
fputc:
向文件流中一次写一个字符
gets:
从流中读取一行字符串 知道遇到换行,才停止读取
puts:
简单来说是,输出字符串
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:
本例向文件中格式化输出学生信息
#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;
}
#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:
将数据以二进制的形式写入文件
#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:
指定位置读写
#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:
该函数用来判断系统读取文件时,是否正常结束
系统读取文件完毕时,会返回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;
};