C语言宝典(持续更新)

1、基本知识和概念

指针变量操作

正确操作:

  • 赋值
  • 解引用
  • 取址
  • 指针与整数相加减:结果为指针,加减单位等于指针指向的数据类型大小
  • 指针递增和递减
  • 指针求差:相减的两个指针指向同一数组的不同元素,差值单位与数组类型的单位相同
  • 比较
  • (void *)类型在gcc编译器等同于(char *)

错误操作:编译时报错

  • 数组名做运算
  • 指针变量相加
  • 指针变量相乘

const的用法

  • 指向const的指针能被const数据和非const数据的地址赋值
double rate[] = {1.12, 1.22};
const double locked[] = {2.45, 55.3};
const double *pc = rate; /*可以*/
pc = locked; /*可以*/
  • 普通指针只能被非const数据的地址赋值(编译时报错)
const double locked[] = {2.45, 55.3};
double *pc = locked; /*不可以*/

字符串字面量

  • 字符串字面量之间没有间隔或者空白分割,则视为串联;
  • 双引号括起来的内容被视为指向该字符串储存位置的指针;
  • 字符串字面量属于静态存储类别(static storage class),表示该字符串只会被存储一次,在整个程序的生命周期内存在;
  • 相同的字符串在内存中只有一份;格式化输入输出相同的字符串也只有一份;(与编译器相关);
/*
* 1、STR1、STR2、str5都指向了同一个字符串地址;
* 2、str3数组有自己单独的地址空间;
* 3、str4数组在运行时为其分配空间并赋值,是静态存储区字符串的副本; * 4、格式化输入输出相同的字符串也只有一份;
*/ #include <stdio.h> #define STR1 "I am a student." #define STR2 "I am a student." char str3[] = "I am a student."; int main(void) { char str4[] = "I am a student."; const char *str5 = "I am a student."; printf("%p\n", STR1); printf("%p\n", STR2); printf("%p\n", str3); printf("%p\n", str4); printf("%p\n", str5); printf("the string size is:%u\n", sizeof(STR1)); printf("the string size is:%u\n", sizeof(STR2)); printf("the string size is:%d\n", sizeof(STR1)); return 0; }
输出结果:
0x1055c
0x1055c
0x21028
0x7eaeb1b4
0x1055c
the string size is:16
the string size is:16
the string size is:16
/* 部分数据段汇编代码 */
str3:
    .ascii  "I am a student.\000"
    .section        .rodata
    .align  2
.LC0:
    .ascii  "I am a student.\000"
    .align  2
.LC1:
    .ascii  "%p\012\000"
    .align  2
.LC2:
    .ascii  "the string size is:%u\012\000"
    .align  2
.LC3:
    .ascii  "the string size is:%d\012\000"

空字符和空指针

  • 从概念上是不同类型的0
  • 空指针:指针类型,代表无效地址,占用4个字节
  • 空字符:字符类型,占用1个字节

字符串输入输出函数

  • scanf:只能读取一个单词。可设置字段宽度防止溢出,以非空字符开始读取,非空字符结束。
  • gets:从标准输入读取一行,直至遇到换行符停止,替换换行符为空字符。因为没有限制输入大小,容易发生缓冲区溢出。
  • fgets:第二个入参N代表读取最大字符数。读取N-1个字符或者换行符停止。读到文件结尾时返回空指针。
  • gets_s:c11新增可选函数,读到最大字符数时还没读到换行符,将会数组首字符设置为空字符,丢弃后续输入;返回空指针,调用依赖的处理函数,中断或退出程序。
  • puts:输出一个字符串,遇到空字符停止。
  • fputs:针对puts的文件定制版本。
  • printf:灵活的格式化输出函数。

总结:

  • gets()丢弃输入中的换行符,puts()在输出中添加换行符;fgets()保留输入中的换行符,fputs()不在输出中添加换行符。
  • 函数形参为字符串地址时,可定义为两种形式const char *str 或者 const char str[]。通过形参形式可提醒用户,输入实参更可能是数组名、带双引号的字符串、char *类型的变量三种形式的哪一种。

字节对齐

关于字节对齐的两条原则

#pragma pack(n)
原则一: 成员对齐,每个成员的偏移值必须是X的倍数,X = min(n, 该成员对齐宽度)
原则二: 结构体对齐,结构的总大小必须为Y的倍数,Y = min(n, 成员的最大对齐宽度)

例如,在Linux 64位系统中,half占用6字节,long占用8字节,结构体TestUnion的大小为8字节。成员half的对齐宽度为2,大小为6。d的对齐宽度为8。

 

posted @ 2020-06-25 23:26  zephyr~  阅读(362)  评论(0编辑  收藏  举报