0%

C语言基础

变量

C语言基本数据类型

数组和指针

数组指针和指针数组

  • 数组指针

    数组指针,又称为行指针

    例如int (*ptr)[2],从形式上看,这是一个指针变量,指向包含两个元素的数组

    1
    2
    3
    4
    5
    6
    7
    8
    int a[3][4] = {
    {1, 11, 21, 31},
    {2, 12, 22, 32},
    {3, 13, 23, 33}
    };
    int (*p)[4] = a; // 定义了一个数组指针
    p = a; // 指针p指向二维数组第0行的首地址
    p++; // 此时,指针p指向二维数组第1行的首地址
  • 指针数组

    指针数组,顾名思义,即为存放指针类型的数组。

    二级指针int** p本质上就是一个指针数组,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char str1[] = "Panda";
    char str2[] = "Pikachu";
    char str3[] = "Wangwangdog";
    char str4[] = "Tortoise";

    char *p[] = {str1, str2, str3, str4}; // 指针数组

    for (int i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
    printf("%s\n", p[i]); // 等价于 printf("%s\n", *(p + i));
    }

    程序运行结果为:

    1
    2
    3
    4
    Panda
    Pikachu
    Wangwangdog
    Tortoise

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int a[3][4] = {
    {1, 11, 21, 31},
    {2, 12, 22, 32},
    {3, 13, 23, 33}
    };

    int *p[4];

    /* int型指针数组的初始化 */
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
    p[i] = a[i];

    for (int j = 0; j < sizeof(a[i]) / sizeof(a[i][0]); j++) {
    printf("%d ", *(p[i] + j));
    }
    printf("\n");
    }

    程序运行结果为:

    1
    2
    3
    1 11 21 31
    2 12 22 32
    3 13 23 33

字符串

结构体

结构体对齐原则

#pragma pack(n)对齐数据结构大小的计算方法:

  • 程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16改变对齐系数;

  • 结构体中每个数据都应满足:首地址%min{该数据自身长度,n} =0;

  • 整个结构体长度对齐,即:(本条规则为个人总结,程序验证) 结构体总长度%min{ max{结构体中占用内存最大的数据类型的长度},n } =0;

    例:struct Data数据元素在内存中的分布情况(以32位平台为例)

    1
    2
    3
    4
    5
    6
    7
    8
    struct Data{
    char a;
    short b;
    int c;
    double d;
    char e;
    char f;
    };
  • 不同情形下Data元素在内存中的分布情况

#pragma pack(2) #pragma pack(4)
结构体内存分布01 结构体内存分布02

输入输出

格式化输入输出

格式化字符串

sprintf函数

sprintf()是字符串格式化命令,函数声明为int sprintf (char *__stream, const char *__format, ...),所属头文件为stdio.h,功能主要是把格式化后的数据写入到__stream指向的内存空间。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define BUF_LEN 128
int main()
{
char dest[BUF_LEN] = {0};
char buf[BUF_LEN] = {0};
char name[] = "Panda";
int age = 18;
char hobby[] = "play badminton";

sprintf(dest, "Hello, everyone! My name is %s. I am %d years old. I like to %s.", name, age, hobby);
sprintf(buf, "The memory address of var age = 0x%p.", &age);
printf("%s\n", dest);
printf("%s\n", buf);

system("pause");

return 0;
}

程序运行结果为:

1
2
Hello, everyone! My name is Panda. I am 18 years old. I like to play badminton.
The memory address of var age = 0x00000000007dfd14.

sscanf函数

sscanf()是读取格式化字符串命令,函数声明为int sscanf(const char *__source, const char *__format, ...),所属头文件为stdio.h,功能主要是把__source指向的字符串按照格式化进行分解操作;

sscanf()函数可以通过字符串匹配分解字符串,基本格式为%[set],一般有以下两种情况:

  • %[^set] 表示需要在输入字符串中匹配不在set集合中的其他字符,遇见set集合中的字符时,匹配结束;
  • %[set] 表示需要在输入字符串中匹配在set集合中的字符,遇见不属于set集合中的字符时,匹配结束;
  • 此外,sscanf()常用的格式还包括%*[set],表示忽略set集合中的字符

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define BUF_LEN 16
typedef struct{
int year;
int month;
int day;
}Date;

int main()
{
char *month[] = {"January", "February", "March", "March", "May", "June",
"July", "August", "September", "October", "November", "December"};
char buf[] = "Name:Panda; Sex:Male; Age:18; Birthday:2013-06-30.";

char name[BUF_LEN] = {0};
char sex[BUF_LEN] = {0};
char age[BUF_LEN] = {0};
char birthday[BUF_LEN] = {0};
Date date;

sscanf(buf, "Name:%[^;]%*[; ]Sex:%[^;]%*[; ]Age:%[^;]%*[; ]Birthday:%[^;]%*[.]", name, sex, age, birthday);
sscanf(birthday, "%d-%d-%d", &date.year, &date.month, &date.day);

printf("%s\n", name);
printf("%s\n", sex);
printf("%s\n", age);
printf("%s\n", birthdayInfo);
printf("The birthday of %s is %s %d, %d.\n", name, month[date.month - 1], date.day, date.year);

system("pause");

return 0;
}

程序运行结果为:

1
2
3
4
5
Panda
Male
18
2013-06-30.
The birthday of Panda is June 30, 2013.