C 语言老大哥

唉,C 终究还是大哥

Posted by Elli0t on 2020-06-12

C 语言手册下载:

1
2
apt-get install manual
man 3 函数名

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
man 3 printf
输出:
PRINTF(3) Linux Programmer's Manual PRINTF(3)

NAME
printf, fprintf, dprintf, sprintf, snprintf, vprintf, vfprintf, vdprintf, vsprintf, vsnprintf - formatted
output conversion

SYNOPSIS
#include <stdio.h>

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

#include <stdarg.h>

一些常用函数

printf
  • %d 按十进制整型数据的实际长度输出

  • %u 输出无符号整型(unsigned)

  • %c 用来输出一个字符

  • %f 用来输出实数,包括单精度和双精度,以小数形式输出。不指定字段宽度,由系统自动指定,整数部分全部输出,小数部分输出 6 位,超过 6 位的四舍五入

    • %.mf 输出实数时小数点后保留 m 位,注意 m 前面有个点
  • %o 以八进制整数形式输出

  • %s 用来输出字符串

  • %x(或 %X 或 %#x 或 %#X)以十六进制形式输出整数,这个很重要

  • %x、%X、%#x、%#X 的区别

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # include <stdio.h>
    int main(void)
    {
    int i = 47;
    printf("%x\n", i);
    printf("%X\n", i);
    printf("%#x\n", i);
    printf("%#X\n", i);
    return 0;
    }

    输出结果:
    2f
    2F
    0x2f
    0X2F

metset

copies

setvbuf

Changes the the buffering mode of the given file stream stream as indicated by the argument mode.

strtol

long int strtol(const char *str, char *endptr, int base) 把参数 *str** 所指向的字符串根据给定的 base 转换为一个长整数(类型为 long int 型),base 必须介于 2 和 36(包含)之间,或者是特殊值 0

setbuf()和setvbuf()函数的实际意义在于:用户打开一个文件后,可以建立自己的文件缓冲区,而不必使用fopen()函数打开文件时设定的默认缓冲区。这样就可以让用户自己来控制缓冲区,包括改变缓冲区大小、定时刷新缓冲区、改变缓冲区类型、删除流中默认的缓冲区、为不带缓冲区的流开辟缓冲区等。

strcmp

int strncmp( const char *lhs, const char *rhs, [size_t](dfile:///Users/ybm911/Library/Application Support/Dash/DocSets/C/C.docset/Contents/Resources/Documents/en.cppreference.com/w/c/types/size_t.html) count );

image-20200612155101877

getchar

char a;a=getchar();

当你在键盘上输入一个字符(如输入g)后按回车,那么字符变量a的值就是’g’了。

注意事项:

1、当程序调用getchar时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符也放在缓冲区中)。

当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符。

如果用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键。
2、getchar有一个int型的返回值,当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符。getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕。

指针

C/C++ 中*和&的用法

C中*的用法

  • 乘法运算:x=y*z;
  • 乘法赋值运算:x=y;相当于x=xy
  • 注释:/这里是你的注释/
  • 指针的声明:int p 或 int p; 读法:p 是指向一个整数类型的指针
  • 复合指针: int **p; 或 int ** p; 读法 p 是一个指向一个指向整数类型的指针的指针。(同样道理, int***p等等)
  • 解引用: x=*p 把指针 p 指向的值赋值给 x

&在C语言中的用法(解引用)

  • 逻辑与:if((a>1)&&(b<0))
  • 位运算与:x=a&b;
  • 逻辑与赋值:x&=y; 与 x=x&y 含义相同
  • 求地址运算符:p=&x; 读法:把 x 的地址赋给 p(指针)

(char *)a的意思是:将 a 强制类型转换为字符指针类型

数组指针与指针数组

void *

void *是一种无类型指针,任何类型指针都可以转为void\*,它无条件接受各种类型。实际上我们在很多接口中都会发现它们的参数类型都是void 。为何要如此设计?因为对于这种通用型接口,你不知道用户的数据类型是什么,但是你必须能够处理用户的各种类型数据,因而会使用 void \。void *能包容地接受各种类型的指针。也就是说,如果你期望接口能够接受任何类型的参数,你可以使用void*类型。但是在具体使用的时候,你必须转换为具体的指针类型。例如,你传入接口的是int*,那么你在使用的时候就应该按照int*使用。

数组指针(也称行指针)
定义 int (*p)[n];
( )优先级高,首先说明 p 是一个指针,指向一个整型的一维数组,这个一维数组的长度是 n,也可以说是 p 的步长。也就是说执行 p+1 时,p 要跨过 n 个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a [3] [4];
int (*p) [4]; // 该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; // 将该二维数组的首地址赋给 p,也就是 a[0] 或 &a[0][0]
p++; // 该语句执行过后,也就是 p=p+1;p 跨过行 a[0] [ ]指向了行 a[1] [ ]

所以数组指针也称指向一维数组的指针,亦称行指针。

指针数组
定义 int *p[n];
[ ]优先级高,先与 p 结合成为一个数组,再由 int * 说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行 p+1 是错误的,这样赋值也是错误的:p=a;因为 p 是个不可知的表示,只存在 p[0]、p[1]、p[2]…p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里 *p表示指针数组第一个元素的值,a 的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3] [4];
for(i=0;i<3;i++)
p[ i ]=a[ i ];
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是 p[0]、p[1]、p[2]
所以要分别赋值。

这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i] [j]

优先级:( ) > [ ] > *

结构体 struct

定义结构体有两种定义方式:

1
2
3
4
5
typedef struct 结构名
{
类型 变量名;
类型 变量名;
} 结构别名1, 结构别名2;

结构名结构别名 都不能直接用,因为它们是结构体这种数据类型的名称,这种方式定义的结构体使用时,需要先声明 结构变量

另一种定义方式为:

1
2
3
4
5
struct 结构名
{
类型 变量名;
类型 变量名;
} 结构变量;
参考链接

https://blog.csdn.net/caozixuan98724/article/details/73395598/

https://www.cnblogs.com/tongye/p/9650573.html

https://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html

数组指针和指针数组的区别