回味C语言

2023-10-31

虽然在实际上没怎么使用C语言了,但是看到C语言的书总是忍不住想看一下(喜欢这种至简,却又有着强大能力的语言),读完书随手写的一些笔记,略有些简单。书还是很喜欢的,推荐给大家(C专家编程)

第一章 C:穿越时空的迷雾


  • 原型决定C语言不支持函数重载
//previous definition is here
void overload(int a)
{
    printf("%d\n",a);
}

void overload(double a)
{
    printf("%lf\n",a);
}
  • 参数传递类似于赋值
void assign(char a)
{
    printf("%d\n",a);
}
//指针类型才会出现这种错误
void assignpoint(char *p)
{
    printf("%s\n",p);
}
//gcc C++ error C warning
int main()
{
    const char a = 5;
    assign(a);
    const char *p = "helloworld";
    //argument is incompatible with prototype
    assignpoint(p);
}  
  • 尽量不要使用无符号类型
int array[5] = {1,2,3,4,5};
//当数组类型发生变化时,这种方式比下面的方法更通用
#define TOTAL_ELEMENTS sizeof(array)/sizeof(array[0])
// #define TOTAL_ELEMENTS sizeof(array)/sizeof(int)

int main()
{
    int d = -1;
    // TOTAL_ELEMENTS类型是无符号整数,d被转化为无符号数
    // 需要强制类型转化
    // if(d<(int)TOTAL_ELEMENTS)
    if(d<TOTAL_ELEMENTS)
    {
        printf("hello");
    }
}  

第二章 这不是Bug,而是语言特性

书中的这句话成了现在的经典啊
this is not a bug,it’s a feature

  • switch
#include<stdio.h>
int main()  
{
    const int two = 2; //现在编译器不会出现错误
    //case条件不能是变量,只能是整形常量包括char, short, int, long
    int i=2;
    //一条switch语句最多257个case标签
    //8bit的所有情况加上EOF
    switch(i)
    {
        //没有break则顺序执行,不执行default
        case 1:printf("case 1\n");
        //default 打错了也能编译通过
        defult:printf("default"); //default 顺序不影响
        case two:printf("case 2\n");
        case 3:printf("case 3\n");
    }
}
  • 字符串自动连接
#include<stdio.h>
int main()  
{
    //加斜杠空格,第二行前面的空格也算在内,没有反斜杠会报错
    printf("a favorite children's book\
    is muffy\n");
    //新风格字符串自动连接
    printf("a favorite children's book"
    " is muffy\n");
    //定义数组时要注意
    char *strs[] = {"red""green","yellow"};
    printf("%s\n",strs[0]);
}
  • 符号重载
#include<stdio.h>
int main()
{
    int *p;
    int i=3,apple;
    p=&i;
    // invalid operands to binary expression ('unsigned long' and 'int *')
    apple = sizeof(int)*p;
}
  • 运算符优先级
优先级 表达式 实际结果
.的优先级高于* *p.f *(p.f)
[]高于* int *ap[] int *(ap[])
函数()高于* int *fp() int *(fp())
==和!=高于位操作符 val&mask!=0 val&(mask!=0)
==和!=高于赋值符 c=getchar()!=EOF c=(getchar()!=EOF)
算数运算符高于移位运算符 msb<<4+lsb msb<<(4+lsb)
逗号运算符最低 i=1,2 (i=1),2

* 最大一口策略

int main()
{
    int x=2,y=3,temp;
    temp = y+++x;
    printf("%d\n",temp);
    // temp = y+++++x; //缺少空格
    // temp = y++ ++ +x; //不能编译通过
    printf("%d\n",temp);
}
  • lint程序

第三章 分析C语言的声明

C语言的声明是被玩坏了的,还是希望简单点的好。
不过偶尔烧脑,也不失为一个明智的决策

  • 声明复杂性

    1. 函数的返回值不能是一个函数,foo()()是非法的
    2. 函数的返回值不能是一个数组,foo()[]是非法的
    3. 数组里面不能有函数,foo是非法的

下面是合法的 * 函数的返回值允许是一个函数指针,如int(* fun())(); * 函数的返回值允许是一个指向数组的指针,如int(fun())[]; 数组里面允许有函数指针,如int(fun[])() 数组里面允许有其他数组int foo[][]

  • 位段,无名字段和填充字段
#include<stdio.h>
int main()
{
    struct dog
    {
        char id;
        short height;
        int weight;
    };
    //字节对齐
    printf("%lu\n",sizeof(struct dog));//8
    //位填充不影响字节对齐
    struct pid_tag
    {
        unsigned int inactive : 1;
        unsigned int :1; //1个位填充
        unsigned int refcount : 6;
        unsigned int :0; //填充到下一个字边界
        short pid_id;
        short :0;
        struct pid_tag *link;
    };
    printf("%lu\n",sizeof(struct pid_tag));//16
}
  • typedef 和 #define
#include<stdio.h>
int main()
{
    #define peach int  //没有分号
    unsigned peach i;  //incorrect

    typedef int banans;
    // unsigned banans i; //incorrect

    #define int_ptr int *
    int_ptr chalk,cheese;  //chalk是指针,cheese是int

    typedef char * char_ptr;
    char_ptr Bentley,Rolls_Royce; //两个char*
}

第四章 令人震惊的事实:数组和指针并不相同

  • 左值和右值

左值是地址,而右值是地址的内容

声明为指针,定义为数组 会出错
原因如下
char a[9] = “abcdefgh” c = a[i]
编译器符号表示具有一个地址9980
运行时步骤1: 取i的值,将它与9980相加
运行时步骤2: 取地址(9980+i)的内容

char *p = “abcdefgh” c = p[i]
编译器符号表示具有一个p地址4624
运行时步骤1: 取地址4624的内容9980
运行时步骤2: 取i的值,将它与9980相加
运行时步骤3: 取地址(9980+i)的内容

通过上述两步,即可理解当声明为指针,定义为数组时会出错
首先当p声明为指针时,会依照三步来获取内容,错误出现在步骤1
需要对数组名取内容,实际是数组第一个元素的值,加上偏移量
得到错误的结果

第五章 对链接的思考

  • 链接库

使用vc编译器
cl –c cppfile 生成obj文件
静态链接库
lib objfile 生成lib文件
动态连接库
__declspec(dllexport) //必须添加,导出函数,这样就会有lib文件生成
link /dll objfile 生成dll文件
查看动态链接库 dumpbin /exports dllfile

windows下调用动态链接库

#include<iostream>
#include<windows.h>
using namespace std;

// windows 下的调用方式
int main()
{
    typedef void (*pfunc)(void);
    HINSTANCE hDll=LoadLibrary("E:\\CClearning\\DynamicLinkLibrary\\dll.dll");
    if(!hDll)
    {
        cout<<"LoadLibrary Error: "<<GetLastError()<<endl;
        return 0;
    }
    cout<<"dll.dll的句柄地址:"<< hDll << endl;

    //pfunc本身表示指针,不能再用pfunc*
    //pfunc * pf=(pfunc *)GetProcAddress(hDll,"?greet@@YAXXZ");

    pfunc pf=(pfunc)GetProcAddress(hDll,"?greet@@YAXXZ");
    if(!pf)
    {
        cout<<"GetProcAddress Error: "<<GetLastError()<<endl;
        return 0;
    }
    cout<<"dll.dll内的greet()函数的地址:"<< pf <<endl;

    pf();
    //(*pf)();
    //使用完毕后,释放dll文件
    FreeLibrary(hDll);
}

使用gcc编译器
g++ -c cppfile 生成.o链接文件
静态连接库 ar rc liblib.a lib.o 生成.a静态文件
要指定生成文件名liblib.a
然后链接静态库
g++ gccstatic.cpp -L . -l lib
L指定要搜索的库的路径,l指定要搜索的库的名字,可以省略libXXX.a
当然MinGW可以使用这种方法g++ gccstatic.cpp liblib.a

动态连接库
g++ dll.cpp -shared -o libdll.so 生成.so动态链接文件
然后链接动态库
g++ gccdynamic.cpp libdll.so

第六章 运行时数据结构

  • a.out中各个段,数据段,代码段

  • setjmp可以实现异常处理

#include<stdio.h>
#include<setjmp.h>

jmp_buf buf;

// warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
banana()
{
    printf("in banana() \n");
    longjmp(buf,1);
    //一下代码不会被执行
    printf("you'll never see this,because i longjmp'd");
}

main()
{
    if(setjmp(buf))
    {
        printf("back in main\n");
    }
    else
    {
        printf("first time through\n");
        banana();
    }
}

第七章 对内存的思考

内存中的分段和分页

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

回味C语言 的相关文章

  • 如何防止 Json.NET 将枚举转换为字符串?

    下面的课 public class RequestSections RequestBase public RequestSections Command c Dictionary
  • URL 的正则表达式

    我已经编写了正则表达式来验证 URL 它可以是这样的 example com www example com http www example com http www example com https www example com h
  • 到底什么是“位填充”或“填充位”?

    我只是在互联网上找不到任何关于 位填充 真正含义的详细解释 并且在 Stack Overflow 上也没有找到与位填充相关的线程的任何答案 我还搜索了 ISO 9899 1990 其中提到了 位填充 但没有根据我的需要进行解释 我在网上找到
  • 如何在函数中将结构成员作为指针传递?

    问题是我有一个结构是另一个 主要 结构的成员 我编写了一个函数来清除第一个结构 它需要一个指向结构的指针 我想使用该函数来清除主要结构内的结构 但我不确切知道哪种方法是正确的 为了更好地解释它 这里有一些代码 我有一个结构 定义为 type
  • 模拟 EF core dbcontext 和 dbset

    我正在使用 ASP NET Core 2 2 EF Core 和 MOQ 当我运行测试时 我收到此错误 消息 System NotSupportedException 非虚拟 可在 VB 中重写 成员上的设置无效 x gt x Movies
  • 将 gcov 与 CMake/CDash 结合使用的详细指南?

    我在我的项目中使用 CMake 并设置了 cdash 服务器以进行连续 夜间构建 一切运行良好 通过设置 crontab 我们可以将每小时 每晚的构建 测试结果自动上传到我们的 cdash 服务器 我的下一步是将测试覆盖率报告添加到构建中
  • 混合 VS2012 平台工具集

    我们正在从 VS2005 切换到 VS2012 update 2 我们正在构建大量 主要是控制台 本机 C 无 MFC ATL 可执行文件 它们使用几个常见的静态链接库 这些可执行文件主要在 Win7 计算机上运行 但有些也部署在较旧的 X
  • DLL 需要访问其应用程序的符号

    在 C 中 DLL 是否可以访问加载它的应用程序的某些符号 我有一个加载插件 dll 的应用程序 这些插件需要访问该应用程序的某些API 是否可以在不创建共享此 API 的新 DLL 的情况下实现此目的 函数指针结构适合这种情况吗 示例 主
  • 接口中的私有成员

    是否可以在 NET 接口中创建私有成员 我听说现在可以了 但我的 IDE 拒绝了 public interface IAnimal void SetDefaultName string name ChangeName name privat
  • MSBuild 将动态生成的文件复制为项目依赖项的一部分

    我有一个自定义 msbuild 任务 它正在生成一些输出文件到 ProjectA 的输出目录 TargetDir 当前的代码是这样的
  • 通过 Nuke.Common/NuGet.CommandLine 部署 NuGet 包时如何通过 Azure Auth

    我正在尝试通过 Azure DevOps 上的 Nuke 和 CI CD 自动执行 NuGet 包更新 一切都构建得很好 但在 PushNuGet 步骤中 该过程尝试通过弹出窗口向 Azure 进行身份验证 这显然从未在 in devops
  • CS0246 找不到类型或命名空间名称“ErrorViewModel”(您是否缺少 using 指令或程序集引用?)

    我收到 CS0246 错误代码 我正在做一个 MVC net core 项目 我正在将 Razor 合并到我的 C 代码中 我在进行构建时收到此错误 我在最后一行收到错误 有人能帮我解决这个问题吗 global Microsoft AspN
  • 如何定义 Swagger UI 参数的默认值?

    我已将 Swagger Swashbuckle 集成到 NET Core 2 2 API 项目中 一切都很好 我的要求纯粹是为了方便 考虑以下 API 方法 public Model SomeEstimate SomeRequest req
  • Cuda:最小二乘求解,速度较差

    最近 我使用Cuda编写了一个名为 正交匹配追踪 的算法 在我丑陋的 Cuda 代码中 整个迭代需要 60 秒 而 Eigen lib 只需 3 秒 在我的代码中 矩阵 A 是 640 1024 y 是 640 1 在每一步中 我从 A 中
  • 第一个随机数始终小于其余随机数

    我碰巧注意到 在 C 中 使用 std rand 方法调用的第一个随机数大多数时候都明显小于第二个随机数 关于 Qt 实现 第一个几乎总是小几个数量级 qsrand QTime currentTime msec qDebug lt lt q
  • Python 中的 C 指针算术

    我正在尝试将一个简单的 C 程序转换为 Python 但由于我对 C 和 Python 都一无所知 这对我来说很困难 我被 C 指针困住了 有一个函数采用 unsigned long int 指针并将其值添加到 while 循环中的某些变量
  • 访问 Visual Studio 扩展中的当前代码窗格

    我正在编写一个 Visual Studio 2010 扩展 在代码视图中带有右键单击菜单 我希望能够从菜单项事件处理程序检查当前代码 但无法在对象模型中找到执行此操作的位置 如何在 Visual Studio 扩展中访问当前窗口中的代码 E
  • 任何浮点密集型代码是否会在任何基于 x86 的架构中产生位精确的结果?

    我想知道使用浮点运算的 C 或 C 代码是否会在任何基于 x86 的体系结构中产生位精确的结果 无论代码的复杂性如何 据我所知 自 Intel 8087 以来的任何 x86 架构都使用准备处理 IEEE 754 浮点数的 FPU 单元 并且
  • MsBuild 在 Visual Studio Online 上找不到恢复的 NuGet 包

    我尝试构建一个存储在 Visual Studio Online 上的外部 GIT 存储库中的解决方案 它有以下步骤 1 Git 恢复 有效 2 NuGet 恢复 有效 3 构建 不起作用 查看日志时我的第一个猜测是 MsBuild 没有查找
  • GetActiveObject() 与 GetObject() -- MK_E_UNAVAILABLE 错误

    All 我在将一些 VBA 代码转换为 C 时遇到一些问题 我们有一个充当本地 COM 服务器的第 3 方应用程序 在我们使用的VBA代码中获取对象 获取对现有对象的引用 e g Set appHandle GetObject ProgId

随机推荐

  • R中使用foreach时清理内存

    foreach能较大的提高计算速度 但是R不会自动清理内存 导致服务器内存经常占用过高 因此使用时需要及时清理内存 以如下例子所示 我需要读取一批excel文件 在运行下面的代码前 经过4次测试 Rstudio的内存情况是这样的 Mb 23
  • VMware安装虚拟机(小白看了都会哦)

    一 什么是VMware VMware是一款运行在windows系统上的虚拟机软件 可以虚拟出一台计算机硬件 方便安装各类操作系统 如Windows Macos Linux Unix等等 虚拟机 VM 是一种创建于物理硬件系统 位于外部或内部
  • 质疑百度的“国学”

    2006年11月03日 18 07 00 百度 这个名字取得非常好 他有一个广告 也不错 这些无不在向人们展示 汉语 的魅力和中国文化的底蕴 才可能构成今日 世界有Google 中国有百度 的格局 但是从百度其中一个产品 国学 来看 百度做
  • 反射、线程

    反射 如何在程序运行的情况下去创建另外一个对象 JAVA反射机制是在运行状态中 对于任意一个类 都能够知道这个类的所有属性和方法 对于任意一个对象 都能够调用它的任意一个方法和属性 这种动态获取的信息以及动态调用对象的方法的功能称为java
  • CNN浅析和历年ImageNet冠军模型解析

    版权声明 作者 黄文坚 本文为大数据杂谈4月13日微信社群分享内容整理 最新人工智能论文 http paperreading club 今天在这里我给大家讲解一些深度学习中卷积神经网络的原理和一些经典的网络结构 卷积神经网络原理浅析 卷积神
  • 苹果系统版本依次顺序_iphone所有型号上市顺序

    Ready 本期给大家讲讲iphone所有型号上市顺序 第一代iPhone于2007年1月9日由苹果公司前首席执行官史蒂夫 乔布斯发布 并在2007年6月29日正式发售 第二代iPhone 3G于2008年6月10日由美国苹果公司的掌门人史
  • 【Linux之shell脚本实战】统计 Linux 进程相关数量信息

    Linux之shell脚本实战 统计 Linux 进程相关数量信息 一 脚本要求 二 检查本地服务器状态 1 检查系统版本 2 检查系统内核版本 三 配置脚本注释模板 1 编辑 vimrc 文件 2 检查模板生效情况 四 编写ps aa s
  • 0基础速通MySql基础

    一 基本配置 经过一系列配置后 可以与客户端进行连接 二 基本操作 数据模型 1 关系型数据库 RDBMS 概念 建立在关系模型基础上 由多张相互连接的二维表组成的数据库 2 数据模型 MySQL是关系型数据库 是基于二维表进行数据存储的
  • 正点原子阿波罗STM32F429开发板资料发布,采用底板+核心板

    正点原子阿波罗STM32F429开发板资料发布 采用底板 核心板 https www amobbs com thread 5654611 1 1 html 正点原子STM32开发板 http www openedv com docs boa
  • IP addr添加网络的使用

    IP addr 添加网络的使用 添加IP到网口 root localhost ip addr add 192 168 10 100 24 dev em1 查看添加的IP root localhost ip addr show 移除添加的IP
  • 卸载或重新安装JDK出现"Windows Installer程序包有问题,此安装需要的DLL不能运行"解决方法(转)

    首先确保windows installer服务是开启的 运行services msc 看看windows installer服务是否启动 先启动看看能否解决 当然本人的是一直启动着的但还是卸载不了 想办法去删注册表却删不全 总是没法解决 之
  • 期货反向跟单的四大跟单禁忌

    对于在反向跟单路上的朋友 经典的 二八定律 这么完美 它依然坚不可摧 但是跟单落地的结果却不一定能成功 反向跟单经验已经做过多次介绍 不过成功各有不同 但是误区无非就以上几个 1忌 不加筛选 盲目乱跟 跟单的样本数据 必须经过筛选 不能不管
  • Arthas & GC日志-JVM(十八)

    上篇文章说jvm的实际运行情况 Jvm实际运行情况 JVM 十七 Arthas介绍 因为arthas完全是java代码写的 我们直接用命令启动 Java jar arthas boot jar 启动成功后 选择我们项目的进程 进入我们可用d
  • Uniapp学习之从零开始写一个简单的小程序demo(新建页面,通过导航切换页面,发送请求)

    先把官网文档摆在这 后面会用到的 uniapp官网文档 https uniapp dcloud net cn vernacular html 一 开发工具准备 1 1 安装HBuilder 按照官方推荐 先装一个HBuilder 下载地址
  • 修复maven缓存导致Jenkins打包失败

    问题 笔者近期在公司搭建了一个内网的nexus 所以每次有新项目要部署到Jenkins时需要使用脚本将相关依赖导入到nexus上 近期笔者在Jenkins配置了一个item报错 然后将相关依赖导入nexus中 再次打包时出现下面这段异常 笔
  • 【VUE】在vue项目实践当中使用swiper轮播图教程

    步骤 1 安装vue awesome swiper npm install vue awesome swiper S 2 在vue项目中引用vue awesome swiper main js import VueAwesomeSwiper
  • Java是面向过程语言还是面向对象语言?

    目录 一 面向过程语言 二 面向对象语言 三 Java是面向过程语言还是面向对象语言 一 面向过程语言 面向过程语言是一种编程范式 它将程序设计看作是按照一定的步骤或流程进行处理的过程 在面向过程语言中 程序员需要自己定义数据结构和算法 并
  • linux的链接方式

    linux的硬链接和软链接 1 链接的概念 Linux链接分两种 一种被称为硬链接 Hard Link 另一种被称为软链接也叫符号链接 Symbolic Link 默认情况下 ln命令产生硬链接 2 硬链接 在Linux文件系统当中 保存在
  • 年入50万,程序员的第二条赛道

    大家好 我是厂长 我有个朋友 叫佩佩 这几年我亲眼见证了她从月薪6千 到年入百万 她曾经靠一条短视频带货就赚了30万佣金 最近 我看到她在做小红书无货源电商这个风口项目 两个月就做到了单店30万的战绩 她说2023年是小红书电商元年 0粉
  • 回味C语言

    虽然在实际上没怎么使用C语言了 但是看到C语言的书总是忍不住想看一下 喜欢这种至简 却又有着强大能力的语言 读完书随手写的一些笔记 略有些简单 书还是很喜欢的 推荐给大家 C专家编程 第一章 C 穿越时空的迷雾 原型决定C语言不支持函数重载