网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
03月11日漏签0天
c语言吧 关注:801,924贴子:4,376,398
  • 看贴

  • 图片

  • 吧主推荐

  • 视频

  • 游戏

  • 1 2 下一页 尾页
  • 22回复贴,共2页
  • ,跳到 页  
<<返回c语言吧
>0< 加载中...

从头看一遍《C和指针》,随手写一些经验和感悟吧

  • 取消只看楼主
  • 收藏

  • 回复
  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
不定时更新。主要说一下自己对里面的一些理解。从头开始。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
我下面的软件调试以VS2005为工具。也欢迎问问题的,可以分析,但是不代写代码。编程还是要靠自己的。


2026-03-11 10:00:42
广告
不感兴趣
开通SVIP免广告
  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
第一章 快速上手
直接从1.1.1开始。前面那段程序可以不用看,没学过C的话看了也是一头雾水。
我们说说空白和注释。
关于空白:
为了代码看起来规范易读。常用的就是tab键按层次缩进。
关于注释:
刚开始写程序的时候总是不喜欢写注释,后来花了很长时间才培养了注释的习惯。
为什么要写注释?注释有什么用呢?答案就是便于理解,便于维护。以后再看的时候,你自己都不一定知道自己当初写的代码是什么意思,真的,我曾经就是。
什么时候需要注释呢?当你建立了一个工程,文件较多,函数较多,相互之间调用较多,这个时候你就需要注释了。当然如果你就几十行代码,不写也罢。
注释怎么写呢?单行注释以”//”开始。多行注释以”/*”开始,以”*/”结束。
对于变量的注释,简要说明变量用途即可: int g_readCnt; // 读取次数计数
对于函数的注释,最少要有这几个信息:1.函数的用途;2.参数的意义;3.返回值说明。比如:
/******************************************************************************************
// @fn: Jlib_Xor 异或计算
// @Param: buf需要计算的buf指针
// len 从buf开始的计算长度
// @return: 异或值
// CreateDate:
// Modify:
// Author:
********************************************************************************************/
Jl_uint8Jlib_Xor(pJl_uint8 buf,Jl_uint32 len);


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
1.1.2 预处理命令
#define 的作用是很强大的。你可以把它理解为一种替换。比如定义#define MAX_NUM 8,那么程序中凡是遇到MAX_NUM都会自动替换成8。
预处理命令有两点需要注意,
1.是#define语句后什么都不跟,不可以跟”;”。
2.在使用#define时要注意在替换后可能会发生的错误。试试比较#define SQURE(x) x*x和#define SQURE(x) (x)*(x)。
我们逐个分析一下。首先是最糟糕的这种#define SQURE(x) x*x。在int x = SQURE (2);时是可以正常使用的,但是int x = SQURE (2+3)时,你期望输出25,但是实际上你得到的值是11.为什么呢?看一下怎么替换的,2+3替换x后得到的是2+3*2+3=11.问题产生的原因是运算符优先级。解决方法就是使用”()”运算符。
更多的预处理命令后面再说。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
1.1.2 main函数
凡是程序,都需要一个入口。而main函数就是这个入口,程序从这里开始执行。不同的环境下,main函数的写法是不同的,但作用都一样。像我们常见void main(),int main(),VS2005控制台默认的main函数是int _tmain(intargc, _TCHAR* argv[]),win32默认的main函数是int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)等等等等。
目前需要知道的就是每个程序都一定会有一个main函数,这里是程序运行开始的地方。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
后面几节就不说了,直接跳到第二章,不过还是建议看一下。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
2.1 环境
使用命令行的话,需要看这个。个人对这个没怎么用过,所以在这里不讲了,免得误导了别人。我都是直接用vs的。
2.2.1 字符
主要注意一下转义字符。
2.2.2 -2.2.3 看书吧,没什么好说的。
2.2.4 标识符 变量、函数、类型的名字不能和关键字重复。
其他的看书吧,没什么好说的。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
第三章 数据类型
C语言里有4种基本数据类型:整型、浮点型、指针、聚合类型(数组、结构等)。
3.1.1 整型
字符、短整型、整形、长整型。每一种又都分为有符号和无符号两种。由于编译器的不同,有时候在不同环境下,位数并不一定是一样的。一般而言字符型8位,整型16位,长整型32位。具体的还是要看变异环境。
就我个人而言,喜欢用下面的方式来定义数据,以方便程序移植。
我会建立一个头文件”commDefine.h”
在这里我会这样声明
// 数据类型定义
typedef char CHAR;
typedef signedchar S8;
typedef signedshort int S16;
typedef signedint S32;
typedef unsignedchar U8;
typedef unsignedshort int U16;
typedef unsignedint U32;
typedef float F32;
typedef double F64;
typedef signedint BOOL;
当我发现我使用的数据类型不兼容于当前的环境时,我就修改typedef。


2026-03-11 09:54:42
广告
不感兴趣
开通SVIP免广告
  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
还是有必要说明一下枚举类型。
枚举类型常用于已知的固定的场合。比如曾经做过的一个项目中,需要控制许多个电机,为了使用方便。
// 电机枚举类型
typedef enum
{
ADD_SAMPLE_UD_M, // 加样升降电机
ADD_SAMPLE_D_M, // 加样转向电机
DISK_M, //圆盘电机
ADD_SAMPLE_M, // 加样电机
MAG_BEAD_M, // 磁珠搅拌电机
}MOTOR_GROUP1_ID;
MotorParam g_mGroup1Param[MAX_MOTOR_GROUP1_NUM];
在我需要用到某个电机时
g_mGroup1Param[ADD_SAMPLE_UD_M].pulParam.mPin.GPIO_Pin= M_AS_UD_PUL; // 脉冲光耦
这样写的好处就是便于理解代码。当然你可以不用这种方式,直接使用数字或者宏定义也可以。
需要注意的是如果不显式的赋值,那么默认从0开始,并依次递增。也就是等效于下面
typedef enum
{
ADD_SAMPLE_UD_M = 0, // 加样升降电机
ADD_SAMPLE_D_M = 1, // 加样转向电机
DISK_M = 2, // 圆盘电机
ADD_SAMPLE_M = 3, // 加样电机
MAG_BEAD_M = 4, // 磁珠搅拌电机
}MOTOR_GROUP1_ID;


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
关于变量声明之后,我想说一个很重要的问题。那就是初始化。虽然有的环境允许变量在使用之前可以不赋值,但是不赋值会带来的问题是不确定的。可能是0,也可能是一个随机的数。吧里看到过好多的求助贴,很多原因都是没有初始化。
3.3 typedef
我很喜欢用typedef。typedef可以为数据类型定义新的名字。比如上面所举的例子。
好处就是可以减少声明变得很长的危险。你要修改程序中所使用的数据类型时,你会发现修改typedef会比修改程序中所有和这种类型相关的变量和函数要方便的多。
3.5 作用域
这一节其实是很重要的。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
我以前不怎么关注这东西。都是稀里糊涂就用了。下面说说自己的理解吧,不一定全对,希望指正。
3.5作用域
作用域顾名思义就是可以被使用的区域。根据书里面,作用域分为四种类型:文件作用域、函数作用域、代码块作用域、原型作用域。
代码块作用域:在”{}”之间的所有语句成为一个代码块。在代码块开始位置声明的标识符都具有代码块作用域,这代表着这些标识符可以被这个代码块中的所有语句访问。此外,函数定义的形参在函数体内部也具有代码块作用域。
代码块嵌套时,如果内层的标识符有和外层重名的,那么内层的代码块就会自动隐藏外层的标识符。但是最好避免这种情况。虽然不影响运行,但是在调试的时候会把自己看晕的。
文件作用域
在代码块之外声明的标识符都具有文件作用域。从声明开始到文件结束都可以访问它。#include包含到其他文件中的声明相当于直接写到了其他文件中,它的作用域不局限于头文件结束。
原型作用域
仅适用于在函数原型中声明的参数名。原型和函数定义不同,参数的名字并不是必须的。当然你要加的话,可以起任何名字,并且可以不和定义中的形参名相同。
函数作用域
看了一下,主要goto语句中会用,我也没用过,不说了。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
语句之if
if (exp)
sta1
else
sta2
sta1或者sta2可以是一句语句或者是代码块。如果是代码块,{}必不可少的吧。
exp表达式避免无效。比如写错一个if (x = 1)等着头疼吧、
多个if else时。
if (x <=0) // 当x<=0时
sta1;
else if (x <100)// 当0<x<100时
sta2;
else if (x <200)// 当 100<=x<200时
sta3;
else//当x>=200时
sta4;


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
何时用while?何时用for?
大多数时候是可以通用的。
但是while使用于满足某一条件退出循环,但是不知道会执行多少次的时候更加容易让人理解。for使用于已知会循环多少次时更加容易让人理解。
do while是不管三七二十一,先执行一遍再说。执行完这一遍看条件是退出还是继续。
break和continue
break是直接跳出循环,也就是整个循环体已经结束了。
continue是中断当前的这次循环,不执行continue后续语句,直接执行下一次循环。


  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
swicth
switch (n)
{
case 1:
case 2:
语句1;// n ==1 或者 n == 2都会执行语句1
break;
case 3:
语句2;// n ==3会执行语句1
break;
case 4:
break;
default
语句;//其他所有情况执行这句
}


2026-03-11 09:48:42
广告
不感兴趣
开通SVIP免广告
  • ToFourier
  • 强能力者
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
左值和右值
虽然它的定义和C语言风格不太符合。左值就是可以出现在赋值号左边的东西,右值就是可以出现在赋值号右边的东西。
左值必须可以预料到存储结果的地址才能成为左值,而右值应该是个可以预料到它的值的东西。
隐式类型转换和算术转换
隐式类型转换:
C的整型运算总是至少以缺省整数类型的精度进行的。
char a,b,c;
…
a = b + c;
b和c的值被提升为缺省整型,再执行加法运算。运算结果是个缺省整形,会被截短,保留低8位,存储于a中。
算术转换:
若某个操作符的各操作数属于不同的类型,除非其中一个操作数转换为另一个操作数类型,否则操作无法进行。
寻常算术转换:
long double >double > float > unsigned long int > long int > unsigned int >int
如果某个操作数的类型排名较低,那么它首先转换为另一个操作数的类型然后执行操作。
较为常见的问题就是涉及到int和float运算的时候。比如:
float x;
int a = 2, b =4;
x = a / b;
你得到的数值肯定不是你想要的0.5。理想的方式是x = (float)a/b;或者将两个操作数全部转换为float类型。
还有一个问题就是计算结果溢出。比如
int a = 60000, b= 60000;
int c = a * b;
long d = a * b;
两种方法都不会得到正确结果。
a * b的结果是个int型数值。int c = a * b;时结果溢出。long d = a * b;时赋给c的值是一个由int转型为long的数据,相当于是long d = c;处理方式同上long d = (long)a * b;


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 1 2 下一页 尾页
  • 22回复贴,共2页
  • ,跳到 页  
<<返回c语言吧
分享到:
©2026 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示