C 语言避坑指南

简介: C 语言避坑指南

 👉引言💎


学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。 热爱写作,愿意让自己成为更好的人............

铭记于心
🎉✨🎉我唯一知道的,便是我一无所知🎉✨🎉


C 避坑指南


一、基础|基本常识类


  • 注意逻辑运算符的短路效应
  • else只跟最近的if相匹配
  • c语言本身不提供输入输出语句,靠标准函数库实现
  • putchar 输出的是字符,,c语言函数内部 不能够嵌套定义 函数
  • 存储类型 有 auto ,static , register(寄存器) , extern(外部),全局变量默认为 static
  • 未指定存储类别的变量,其隐含的存储类别为 auto


1 运算符类型


  • 对于%,需要%%才能转义,而不是\
  • 逗号运算符优先级最低,整个逗号表达式的值就是 最右边表达式的值


image.png

image.png


  • char类型对于字符串会取最低位字符

image.png

  • 这个就是 每个字符占一个字节,int4个字节,被赋值'328'后,每个字节位置则是 0 51 50 56, 换成二进制后再转换为int即为3355192

image.png

  • 只是逗号表达式返回最右边的值,执行还是从左到右

image.png


  • a+=a-=a*a;C中为-4 ,java中为0
    易知Java中对同一变量连续赋值,JVM虚拟机运行结果与c【-8 7 3】不同,而这种写法在python中是不被允许的

image.png


2 占位符|格式化问题


需要注意的是   2 转义字符的使用事项:

  • %5.2s 指输出字符串前2位,占5个空间,右对齐   %d 是忽略并丢弃一个整型字符
  • #的作用 是输出提示(0, 0x)
  • 注意对 char类型赋值时一定看清楚是 数字还是字符,6与'6'是完全不同的
  • %d%i只在scanf时有区别,且前者 只匹配十进制,不匹配的都输出0,后者据情况判断(0x十六进制,0八进制)转10进制
    不匹配直接搞成0

image.png

  • m.n中 m是宽度,负号表示左对齐;n是(具体跟 后面的 d(至少输出的位数) , s(输出的位数) ,f(输出的精度)有关)
    不满足则 用0补齐,高位补0,想想也确实应该 [其实一般用于浮点型]

image.png

  • 如果是%5d 的话则输出  [空格]-123     其实这些 都是符合逻辑的,因为 总不能 下面输出0-123吧,这也不合适

image.png

  • 关于 字符串的输出格式化,字符串位数小于“精度”则输出全部字符串,其它不用管,,大于,则只取“精度”规定的前几个字符

image.png

image.png

  • 对于%d来讲,4代表控制精度为4位,所以高位补0;5代表 设置宽度,所以靠右对齐,共占五个宽度

image.png


3 输入输出问题


  • sprintf(const char * str .....),后面跟printf用法一样,就多了一个指定输出位置str
  • printf与scanf返回值都是由 输出输入字符数量决定
  • scanf(读取时的格式符不能带 .n这样是无效的,也就是只能是 %3d(读取三位有效数字), 而不能%3.2d),且输入时如果不加 输入项,则会抛出运行时异常,而printf("dadw%d")没有输出项也不会报异常
  • 注意如果是 scanf("%c\n"),则输入一个字符回车会陷入死循环,因为回车(空白字符)不会被scanf读取,但是还没有读取\n,也就是他会一直去“读\n”,除非再输入一个 非空白字符

image.png

  • 包括 lf,f格式字符都是默认输出 小数点后六位(超过则四舍五入),但%g可以将无效位数去掉,只输出有效位

image.png

  • getchar( 出错返回-1)

image.png


二、错题 | 程序语句类


  • 1 对于 while(b- -≥0)一定注意,最后b出来的时候是-2,一定要注意这个问题


int s = (b = ++m * m++, --m + b--) + ++b +b--; //相当于b = ++m * m++; s = ( --m + b--) + ++b +b--;
后置++是此运算式子中都不变,运算结束自加(逗号符可以看做结束运算),比如这个m自+后当时是m,但后来m就是m+1,int s = m + m * (m++) * m;


image.png


image.png

  • 2虽然符合c11标准,但各家编译器对其扩展定义不同,比如dev允许变长数组(变长数组不能在定义时初始化),但vs中不允许

image.png


image.png

image.pngimage.pngimage.png


三、进阶 | 指针与函数


scanf(),getchar(),getche(),getch()这些函数缓冲区角度的解释

字符串常量

  1. 相当于 *p = *p+6

image.png

  1. 不能这样给字符数组赋值,另外,上面哪一行在vs中需要加const修饰(指向字符常量)

image.png


  1. 函数指针


int (*t)(int a, int b);
两种调用方式都是可以的
  (*t)(2, 1);
  t(2,1)

数组名是一个地址,也就是一个指针,但不能说是指针变量(不可变),,指针变量的值是一个地址

*p=*q  解引用当左值时是变量,右值时是常量

二维数组传参时局部变量不能用 二级指针,而用数组形式,因为需要指定 一维容量,即 void test(int nums[ ][5] );,字符数组亦是如此

对于数组无法自增,但可以再用个指针指向该数组进行自增移动
P是一个数组指针,指向空间大小为4的数组

printf()多元素输出的时候,存在入栈(同时进行运算),出栈问题,一定注意

strcpy会连 \0结束符 一起复制过去 而strncpy(char *dest, const char *src, size_t len)并不会责添加‘\0’(在字符串长度大于len的情况下,如果小于则会用NULL(\0)填满)

接收含有空格的字符串直接用 gets(str),输出可以puts(str)【且自动换行】


四、进阶 | 结构体及宏定义


  1. 结构体长度的计算
    union的使用受系统大小端的影响  
    栈的生长方向与内存存放规则
    低地址存低位数据 大端模式,低地址存高位数据

image.png

int check_cpu()
    {
    union{
    short a;
    char b;
    }c;
    c.a=1;
    return c.b == 1;
    }小端返回1
enum s------------------------------izes { small=7,medium,large=10,humungous };       
   默认情况下,整型值从0开始。如果对列表中的某个标识符进行了赋值,那么紧接其后的那个标识符的值就比所赋的值大1,然后类推


image.pngimage.png

  • 宏定义是用宏名代替一个字符串,也就是做简单的置换,不做正确性检查。(预编译时不做任何语法检查,只有在编译已被宏展开后的源程序时才会发现语法错误并报错)
  • 宏定义不是C语句,不必在行末加分号,不是c语言本身组成部分。如果加了分号则会连分号一起进行替换
  • #definde出现在A处,则宏名的有效范围为定义命令之后到本源文件之后到本源文件结尾。
  • 可以通过#undef命令终止宏定义的作用域
  • c语言不做const char*修饰以及越界检查,并且如果是cpp,那么检不检查也与编译器有关,比如vs2022检查,dev照样不检查
  • memchr()如果找数字0,则会返回任意地址,因为它会认为0是NULL

🌹写在最后💖: 路漫漫其修远兮,吾将上下而求索!伙伴们,再见!🌹🌹🌹


相关文章
|
算法 程序员 API
C 语言和 C++ 有什么区别?老程序员居然这样理解,不怕你不懂
C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)
154 0
|
6月前
|
Java 编译器 Go
【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析(一)
本文主要梳理自第六届字节跳动青训营(后端组)-Go语言原理与实践第一节(王克纯老师主讲)。
176 1
|
6月前
|
存储 Go C++
【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析(二)
Go 语言中的复合数据类型包括数组、切片(slice)、映射(map)和结构体(struct)。
74 0
|
6月前
|
存储 JSON Java
【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析(三)
在 Go 语言里,符合语言习惯的做法是使用一个单独的返回值来传递错误信息。
76 0
|
6月前
|
机器学习/深度学习 自然语言处理 API
有一点python基础,想玩大模型,不知从何入手。快速入门。
有一点python基础,想玩大模型,不知从何入手。快速入门。
675 0
|
JavaScript 前端开发 安全
每种编程语言都是干嘛的!!!(初学者须知)
每种编程语言都是干嘛的!!!(初学者须知)
|
Rust Java 机器人
是 Rust 太难了,还是主流编程本来就这么折磨人?
本文作者在文章的前部分用了大量笔墨详细描述了自己尝试 Rust 受挫的经历,后半部分分析了 Rust 的问题及发展。自发布以来,这篇文章在 r/rust 上得到了 500 多个赞,在 HN 上有 700 多条评论。我们将其翻译出来,以飨读者,也希望大家可以理性讨论。
542 0
是 Rust 太难了,还是主流编程本来就这么折磨人?
|
Rust JavaScript 前端开发
谁是虽好的语言 ?- 语言选型闲聊(上)
谁是最好的语言?当然是php了 :) 先说一声抱歉,最近工作上有个里程碑要交付,比较忙, 本周的celery源码系列又又要延期了。为了避免大家误以为停更,今天简单聊点别的内容吧。近期我们公司做架构升级,调研了一下各种语言, 包括TypeScript,c#,rust, 还有java和go。这个过程中有一些个人看法,可能会有些偏颇或者不正确的地方,我就简单一说,大家一乐,无意引战。
170 0
谁是虽好的语言 ?- 语言选型闲聊(上)
|
Rust JavaScript Cloud Native
谁是虽好的语言 ?- 语言选型闲聊(下)
近期我们公司做架构升级,调研了一下各种语言, 包括TypeScript,c#,rust, 还有java和go。这个过程中有一些个人看法,可能会有些偏颇或者不正确的地方,我就简单一说,大家一乐,无意引战。
253 0
谁是虽好的语言 ?- 语言选型闲聊(下)
|
XML 存储 Java
不熟悉的编程语言,项目如何开展?
引言 公司中的开发一般是沿着一种核心开发语言如Java、C/C++、PHP进行相关开发。但由于产品新需求、项目新需要,免不了会使用自己不擅长的语言开发。甚至,现在全栈工程师也比比皆是。对于经验不丰富的职场人,如何开展工作呢? 结合我近期的项目经历,我说下我的经验和教训。
200 0
不熟悉的编程语言,项目如何开展?