04C编译过程/32位,64位区别/断言/位域...

C零碎语法

目录

文章目录

  • C零碎语法
    • 1.编译过程
      • 1.2 编译
      • 1.3 汇编
      • 1.4 链接
    • 2.不同位机器,各数据类型所占位数
    • 3.assert() 断言(宏)
      • 3.1缺点
      • 3.2解决办法
      • 3.3使用举例
        • 3.3.1函数开始处检验传入参数的合法性
    • 4.位域
      • 4.1举例
      • 4.2补充
    • 5.typedef/define(取别名)
    • 6.输入输出
      • 6.1scanf()
      • 6.2getchar()
        • 6.2.1扩展
      • 6.3putchar()
        • 6.3.1扩展
      • 6.4puts()
        • 6.4.1扩展
      • 6.5gets()
        • 6.5.1扩展
    • 7.防止多个文件调用重定义
      • 7.1Include Guards
      • 7.2Static Functions
      • 7.3Anonymous Namespaces (C++ only)
    • 8.enum语法
    • 8.结构体指针
    • 9.指针

1.编译过程

请添加图片描述### 1.1 预处理

将所有的#define删除,并且展开所有的宏定义,并且处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等。
处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。
删除所有注释“//”和“/ /”。
添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
保留所有的#pragma编译器指令,后续编译过程需要使用它们。
   $ gcc -E hello.c -o hello.i // 将源文件hello.c文件预处理生成hello.i
                       // GCC的选项-E使GCC在进行完预处理后即停止

1.2 编译

编译过程就是对预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。

$ gcc -S hello.i -o hello.s // 将预处理生成的hello.i文件编译生成汇编程序hello.s
                        // GCC的选项-S使GCC在执行完编译后停止,生成汇编程序

1.3 汇编

汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o的目标文件中
当程序由多个源代码文件构成时,每个文件都要先完成汇编工作,生成.o目标文件后,才能进入下一步的链接工作。

$ gcc -c hello.s -o hello.o // 将编译生成的hello.s文件汇编生成目标文件hello.o
                        // GCC的选项-c使GCC在执行完汇编后停止,生成目标文件
//或者直接调用as进行汇编
$ as -c hello.s -o hello.o //使用Binutils中的as将hello.s文件汇编生成目标文件

1.4 链接

**静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。 **

动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。

2.不同位机器,各数据类型所占位数

请添加图片描述

3.assert() 断言(宏)

定义在 assert.h 中,其作用是如果它的条件返回错误,则终止程序执行

if(假设成立) {
     程序正常运行;
}
else {
      报错&&终止程序!(避免由程序运行引起更大的错误)  
}

3.1缺点

如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。
使用 assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。

3.2解决办法

调试结束后,可以通过在包含 #include 的语句之前插入 #define NDEBUG 来禁用 assert 调用

#include 
#define NDEBUG 
#include

3.3使用举例

3.3.1函数开始处检验传入参数的合法性

一般只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败

int resetBufferSize(int nNewSize) 
{ 
assert(nNewSize >= 0); 
assert(nNewSize <= MAX_BUFFER_SIZE); 
... 
}

4.位域

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可。为了节省存储空间,并使处理简便,C 语言又提供了一种数据结构,称为"位域"或"位段"。

4.1举例

需要一个变量来存储从 0 到 7 的值,您可以定义一个宽度为 3 位的位域

struct
{
  unsigned int age : 3;
} Age;
//age 变量将只使用 3 位来存储这个值

struct bs{
    int a:8;
    int b:2;
    int c:6;
}data;
//data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位

4.2补充

一个位域存储在同一个字节中,如一个字节所剩空间不够存放另一位域时,则会从下一单元起存放该位域。也可以有意使某位域从下一单元开始。

struct bs{
    unsigned a:4;
    unsigned  :4;    /* 空域 */
    unsigned b:4;    /* 从下一单元开始存放 */
    unsigned c:4
    //这个位域定义中,a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占用 4 位,c 占用 4 位。
}

5.typedef/define(取别名)

typedef是类型别名,#define是宏替换。
typedef在编译时处理,#define在预处理时处理。
typedef创建的别名具有类型安全,#define则没有。
typedef可以用于类型声明,而#define通常用于定义常量或宏表达式。
typedef可以用于结构体、联合体、枚举等复杂类型,#define则主要用于简单的文本替换。
typedef unsigned int uint;
#define PI 3.14159

6.输入输出

6.1scanf()

空格、回车也是字符,下面情况也会被读入

scanf("%c%c%c", &a, &b, &c);
输入:a b c
输出:a b
原因:空格被读入,不再作为分隔符
正确输入:abc

6.2getchar()

char c;
c = getchar();
6.2.1扩展

int getchar(void) ==从屏幕读取下一个可用的字符,并把它返回为一个整数。可以在循环内使用这个方法,以便从屏幕上读取多个字符。

6.3putchar()

char c = 'a';
putchar(c);
6.3.1扩展

int putchar(int c) ==函数把字符输出到屏幕上,并返回相同的字符。

6.4puts()

自动加入换行符
printf()支持多种花样输出,而puts()就是输出字符串

puts("请输入一个字符:");
6.4.1扩展

int puts(const char *s) 函数==把字符串 s 和一个尾随的换行符写入到 stdout。

6.5gets()

char str[100];
gets( str);
6.5.1扩展

char *gets(char *s) 函数==从 stdin 读取一行到 s 所指向的缓冲区,直到一个终止符或 EOF。

#include <stdio.h>
 
int main( )
{
   char str[100];
 
   printf( "Enter a value :");
   gets( str );
 
   printf( "\nYou entered: ");
   puts( str );
   return 0;
}
Enter a value :runoob
You entered: runoob

7.防止多个文件调用重定义

7.1Include Guards

#ifndef HEADER_FILE_H
#define HEADER_FILE_H//HEADER_FILE_H是一个唯一的宏,它在头文件第一次被包含时被定义

// 头文件内容

#endif // HEADER_FILE_H

7.2Static Functions

static int myFunction() {
    // 函数实现
}
//函数的作用域就被限制在定义它们的文件内,防止在其他文件中被重定义。

7.3Anonymous Namespaces (C++ only)

namespace {
    // 定义在匿名命名空间中的实体
    void myFunction() {
        // 函数实现
    }
}

8.enum语法

定义枚举类型的变量,变量的取值将被限制

enum Color {
    RED,
    GREEN,
    BLUE
};

enum Color myColor;
myColor = RED; // 赋值

枚举类型的底层类型默认是int,但你也可以指定其他整数类型

enum Color : unsigned char {
    RED,
    GREEN,
    BLUE
};

8.结构体指针

  1. 动态内存分配
    使用指针,你可以在堆上动态分配内存来创建结构体实例,这意味着你可以在运行时根据需要分配和释放内存。

    struct Student *student = malloc(sizeof(struct Student));
    if (student != NULL) {
        // 使用student
        free(student); // 记得释放内存
    }
    
  2. 数组和链表
    指针使得创建结构体数组和链表变得简单。你可以使用指针数组来索引结构体,或者创建一个结构体链表来动态地管理数据。

    struct Student *students = malloc(5 * sizeof(struct Student)); // 分配数组
    // 或者
    struct Node {
        struct Student data;
        struct Node *next;
    };
    
  3. 函数参数传递
    通过指针传递结构体到函数可以避免复制整个结构体,这在结构体很大或者需要修改原结构体时非常有用。

    void updateStudent(struct Student *student, int newId, float newGpa) {
        student->id = newId;
        student->gpa = newGpa;
    }
    
  4. 间接访问
    指针允许间接访问结构体成员,这在你需要通过计算或条件逻辑来确定成员访问路径时非常有用。

    struct Student *pStudent = &student1;
    printf("Name: %s\n", (*pStudent).name); // 通过解引用指针访问成员
    
  5. 多级指针和指针数组
    可以创建指针的指针,或者指针数组,这在处理复杂的数据结构(如树、图)时非常有用。

    struct Student **ppStudent = &pStudent; // 指针的指针
    struct Student (*ppArray)[10] = malloc(5 * sizeof(struct Student[10])); // 指针数组
    
  6. 传递大型结构体
    当结构体较大时,通过指针传递可以减少内存的复制,提高程序的效率。

  7. 函数返回结构体
    函数可以通过返回指向新分配内存的指针来返回结构体,这允许函数动态地创建并返回结构体实例。

    struct Student* createStudent(int id, const char* name, float gpa) {
        struct Student *newStudent = malloc(sizeof(struct Student));
        if (newStudent != NULL) {
            newStudent->id = id;
            strcpy(newStudent->name, name);
            newStudent->gpa = gpa;
        }
        return newStudent;
    }
    

9.指针

请添加图片描述
请添加图片描述
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/675306.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android11 AudioTrack和Track建立联系

应用程序创建AudioTrack时&#xff0c;导致AudioFlinger在播放线程中&#xff0c;创建Track和其对应。那它们之间是通过什么来建立联系传递数据的&#xff1f;答案是共享内存。 创建Track时&#xff0c;导致其父类TrackBase的构造函数被调用 //frameworks/av/services/audiofl…

网络原理——HTTP/HTTPS ---- HTTPS

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 目录 HTTPS加密与解密HTTPS的工作流程使用对称密钥来加密使用非对称密钥 来对 对称密钥进行加密第三方公证总结 HTTPS https本质上就是在http的基础之上 增加了加密层,抛开加密层之后,剩下的部…

USART串口外设

USART介绍 USART&#xff1a;另外我们经常还会遇到串口&#xff0c;叫UART&#xff0c;少了个S&#xff0c;就是通用异步收发器&#xff0c;一般我们串口很少使用这个同步功能&#xff0c;所以USART和UART使用起来&#xff0c;也没有什么区别。 其实这个STM32的USART同步模式&a…

抖店入驻门槛,一降再降,2024年商家入驻抖店最佳的时机来了!

大家好&#xff0c;我是电商糖果 抖店已经发展有四年多的时间了&#xff0c;现在也算是比较成熟的电商平台. 这几年因为直播带货的火爆&#xff0c;再加上抖音的流量支撑&#xff0c;还有抖音在背后的扶持和推广。 让抖店成了电商行业的黑马项目&#xff0c;吸引了不少商家入…

融合通信项目中常见设备有哪些?

在信息化时代的今天&#xff0c;人们对于通讯的需求越来越大&#xff0c;而传统的单一通讯方式已经无法满足现代社会的需要。因此&#xff0c;融合通信系统的出现成为了必然趋势。 融合通信系统对行业发展的作用不仅仅是提高通信效率和降低通信成本&#xff0c;还可以提升管理效…

elementplu父级页面怎么使用封装子组件原组件的方法

一、使用原因&#xff1a; 封装了el-table&#xff0c;表格中有多选&#xff0c;父级要根据指定状态&#xff0c;让其选择不上&#xff0c;需要用到elementplus中table原方法toggleRowSelection 附加小知识点&#xff1a;&#xff08;el-tree刷新树后之前选中的保持高亮setCurr…

COMPUTEX 2024 国际电脑展即将举行,英伟达宣布将Copilot+引入RTX系列设备,赋能游戏本AI助理

COMPUTEX 2024 国际电脑展即将于2024年6月4日至7日在台北南港展览馆1馆及2馆盛大举行。作为业界瞩目的盛会&#xff0c;本次展会不仅吸引了全球各地的科技爱好者&#xff0c;更迎来了AMD CEO苏姿丰博士和NVIDIA首席执行官黄仁勋的精彩演讲。 在展会的开幕之际&#xff0c;图形…

LLM基础知识

LLM背景知识介绍 1 大语言模型 (LLM) 背景 大语言模型 (英文&#xff1a;Large Language Model&#xff0c;缩写LLM) 是一种人工智能模型, 旨在理解和生成人类语言. 大语言模型可以处理多种自然语言任务&#xff0c;如文本分类、问答、翻译、对话等等。 &#x1f4a5;通常&…

【距离四六级只剩一个星期!】刘晓艳四级保命班课程笔记(2)(可分享治资料~)

这一节是专门的听力课程&#xff0c;众所周知&#xff0c;咱们刘晓艳刘老师的口语不是特别的突出&#xff0c;当然口才是一流的☝️。 文章目录 听力预判听前预判 听力过程八大出题关键点视听一致同义转换 听完一道题后平时练习精听步骤 听力预判 听前预判 画关键词&#xff…

【C、C++编译工具】CLion工具介绍与安装

一、问题 最近突发奇想想学学最开始接触的语言C&#xff0c;之前大学的时候用的更多的工具还是VC&#xff0c;工作后慢慢接触了CLion&#xff0c;跟pycharm其实差不多&#xff0c;都是集成开发环境&#xff08;IDE&#xff09; 解释&#xff1a;什么是 IDE&#xff1f; 根据计…

MySQL表的增删改查初阶(上篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

【uniapp】uniapp页面介绍

目录 开发工具&#xff1a;HBuilderX介绍特点和功能 页面简介页面管理新建页面删除页面页面改名pages.json 设置应用首页 页面内容构成template模板区script 脚本区export default 外的代码export default 里的代码 style样式区 页面生命周期Vue2 页面及组件生命周期流程图Vue3…

项目管理软件是什么?五大常用项目管理软件介绍

第一款&#xff0c; 奥博思 PowerProject 项目管理软件 PowerProject 项目管理软件是由国内老牌软件开发商“北京奥博思软件技术有限公司”出品。PowerProject 是一款集项目管理、项目集管理、项目组合管理三位一体的一站式数字化项目管理平台。 官网&#xff08;提供软件免费…

研学活动是什么意思,一看就懂!

可能有很多人不了解研学活动是什么意思&#xff0c;其实研学活动一般是由学校组织的&#xff0c;不仅仅是一场简单的旅行&#xff0c;更是一种教育的延伸&#xff0c;一种知识的实践&#xff0c;一种能力的培养。它让学生走出课堂&#xff0c;走进社会&#xff0c;接触自然&…

AzSubEnum:针对Azure服务的子域名枚举查询工具

关于AzSubEnum AzSubEnum是一款专门为Azure服务量身定制的子域名枚举查询工具&#xff0c;该工具旨在帮助广大研究人员仔细搜索和识别与各种Azure服务相关的子域名信息。 通过结合查询技术和语句&#xff0c;AzSubEnum能够深入分析Azure的域名架构&#xff0c;并系统地探测和收…

亚信安全正式推出5G专网安全测试服务 圆满完成核电客户5G项目落地

近日&#xff0c;亚信安全联合北京触点互动信息技术有限公司成功完成某核电客户5G专网项目&#xff0c;从终端安全&#xff0c;基站&#xff0c;核心网网元&#xff0c;切片安全以及接口安全等重点存在安全风险点进行测试&#xff0c;发现潜藏的安全隐患漏洞&#xff0c;为客户…

【vue】@、@/、../和./的区别

&#xff1a;表示vue语法中v-on的简写&#xff1b;绑定事件的专用格式。当事件触发的时候&#xff0c;函数才会来调用&#xff1b; /&#xff1a;在build文件夹下webpack.base.conf.js找到&#xff0c;便能知道代表什么了; 这里指向src文件夹 . /&#xff1a;表示当前目录下&…

ESP8266在阿里云上线(arduino)

电脑连接上ESP8266的板子 在arduino编写代码&#xff08;arduino按照之前的配置&#xff0c;已安装好esp的开发板和几个库ArduinoJson我选了5.的版本&#xff0c;PubSubclient,Crypto,AliyunIoTSDK并且修改pubsubclient的参数&#xff09; 在项目&#xff0c;加载库&#xff0c…

一个通道,用友BIP获取全量九类电子凭证

在数字化时代&#xff0c;企业运营的效率和准确性已成为衡量竞争力的关键指标。用友BIP电子凭证3.0&#xff0c;作为企业数字化转型的得力助手&#xff0c;以其独特的全通道能力&#xff0c;为企业提供了一站式的电子凭证获取和管理解决方案。这一创新技术不仅简化了繁琐的凭证…

Linux【安全 02】OpenSSH漏洞修复(离线升级最新版本流程)网盘分享3个安装包+26个离线依赖

OpenSSH离线升级最新版本流程 1. 漏洞信息2. 环境说明3.依赖安装3.1 在线安装3.2 离线安装 4.备份卸载4.1 备份4.2 卸载旧版本 5.安装5.1 zlib5.2 ssl5.3 openssh5.3.1 安装5.3.2 配置 6.脚本整理7.文件资源 本文仅针对CentOS7.8版本&#xff0c;其他版本未测试&#xff0c;安装…