Common concepts of C(2)

本文介绍了C语言的基础概念,包括ASCII编码、字符和字符串操作、转义字符、语句分类及注释使用等,帮助初学者理解C语言的基本元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

6、字符和ASCll编码

7、字符串与\0

8、转义字符

9、语句和语句分类

10、注释是什么?为什么写注释?


 

6、字符和ASCll编码

我们知道在计算机中所有的数据都是以⼆进制的形式存储的,那这些字符在内存中分别以什么样的二进制存储的呢?如果我们每个人自己给这些字符中的每字符编⼀个⼆进制序列,这个叫做编码,为了方便大家相互通信,不造成混乱,后来美国国家标准学会(ANSI)出台了⼀个标准 ASCII 编码,C语言中的字符就遵循了 ASCII 编码的方式。

 

我们不需要记住所有的ASCII码表中的数字,使用时查看就可以,不过我们最好能掌握几组特殊的数据:

字符A~Z的ASCII码值从65~90

字符a~z的ASCII码值从97~122

对应的⼤小写字符(a和A)的ASCII码值的差值是32

数字字符0~9的ASCII码值从48~57

换⾏ \n 的ASCII值是:10

在这些字符中ASCII码值从0~31 这32个字符是不可打印字符,无法打印在屏幕上观察

 

单个字符的打印可以使⽤%c来指定格式:

#include <stdio.h>

int main()
{
    printf("%c\n", 'Q');

    printf("%c\n", 81);//这⾥的81是字符Q的ASCII码值,也是可以正常打印的

    return 0;
}

7、字符串与\0

使⽤双引号括起来的⼀串字符就被称为字符串,如:"abcdef",就是⼀个字符串。

字符串的打印格式可以使⽤ %s 来指定,也可以直接打印如下:

#include <stdio.h>

int main()
{
    printf("%s\n", "hello C");

    printf("hello c");

    return 0;
}

C语⾔字符串中⼀个特殊的知识,就是在字符串的末尾隐藏放着⼀个\0字符,这个\0字符是字符串的结束标志。

对于字符串"abcdef",我们实际上看到了6个字符:a,b,c,d,e,f,但是实际上在末尾还隐藏⼀个\0的转义字符,\0是字符串的结束标志。所以我们在使用库函数 printf() 打印字符串或者strlen() 计算字符串长度的时候,遇到\0 的时候就自动停止了。

C语⾔中也可以把⼀个字符串放在⼀个字符数组中,我们在这⾥利⽤下面的代码验证⼀下 \0 的功能。

include <stdio.h>

int main()
{
    char arr1[] = {'a', 'b', 'c'};//arr1数组中存放3个字符

    char arr2[] = "abc"; //arr2数组中存放字符串

    printf("%s\n", arr1);
    
    printf("%s\n", arr2);

    return 0;
}

这样的代码,我调试的时候,观察⼀下 arr1 和 arr2 的内容:

运行结果:

我们可以看到, arr1 字符数组在打印的时候,打印了 a 、 b 、 c 后还打印了⼀些随机值,这就是因为 arr1 在末尾的地方没有 \0 字符作为结束标志,在打印的时候没有停止。

但是 arr2 的打印就是完全正常的,就是因为 arr2 数组是使用字符串常量初始化的,数组中有\0作为结束标志,打印可以正常停止。

 

如果我们在arr1数组中单独放⼀个 '\0' 字符会怎么样呢?

 

 

#include <stdio.h>

int main()
{
    char arr1[] = {'a', 'b', 'c', '\0'};

    char arr2[] = "abc";

    printf("%s\n", arr1);

    printf("%s\n", arr2);

    printf("%s\n", "abc\0def");

    return 0;
}

 

看到三次打印的结果是⼀样的了,都是打印到 \0 的时候就停止了,那从上述的例⼦我们确实能够观察到 \0 的作⽤和重要性的。

 

8、转义字符

转义字符顾名思义:转变原来的意思的字符。

⽐如:我们有字符 n ,在字符串中打印的时候自然能打印出这个字符,如下:

#include <stdio.h>

int main()
{
    printf("abcndef");

    return 0;
]

输出的结果:

如果我们修改⼀下代码,在n的前⾯加上 \ ,变成如下代码:

#include <stdio.h>

int main()
{
    printf("abc\ndef");

    return 0;
}

输出结果:

我们可以看到修改的前后代码输出的结果,截然不同的,那这是为什么呢?

这就是转义字符的问题, \n 是⼀个转义字符表示换行的意思,我们可以简单的理解为 \ 让 n 的意思

发⽣了转变, n 本来是⼀个普通的字符,被 \ 转义为换行的意思。

C语⾔中像这样的转义字符还有⼀些,具体如下:

\? :在书写连续多个问号时使用,防止他们被解析成三字母词,在新的编译器上没法验证了。

\' :用于表示字符常量'

\" :用于表示⼀个字符串内部的双引号

\\ :用于表示⼀个反斜杠,防止它被解释为⼀个转义序列符。

\a :警报,这会使得终端发出警报声或出现闪烁,或者两者同时发生。

\b :退格键,光标回退⼀个字符,但不删除字符。

\f :换页符,光标移到下⼀页。在现代系统上,这已经反映不出来了,行为改成类似于 \v 。

\n :换行符。

\r :回车符,光标移到同⼀行的开头。

\t :制表符,光标移到下⼀个水平制表位,通常是下⼀个4/8的倍数。

\v :垂直分隔符,光标移到下⼀个垂直制表位,通常是下⼀行的同⼀列。

下⾯2种转义字符可以理解为:字符的8进制或者16进制表示形式

\ddd :d d d表示1~3个八进制的数字。 如: \130 表示字符X

\xdd :d d表示2个十六进制数字。 如: \x30 表示字符0

\0 :null 字符,代表没有内容, \0 就是 \ddd 这类转义字符的⼀种,用于字符串的结束标志,其

ASCII码值是0.

代码演示:

#include <stdio.h>

int main()
{
    printf("%c\n", '\'');

    printf("%s\n", "\"");

    printf("c:\\test\\code\\test.c\n");

    printf("\a");

    printf("%c\n", '\130'); //130是8进制,转换成10进制是88,以88作为ASCII码值的字符

是'X'

    printf("%c\n", '\x30'); //x30中的30是16进制,转换成10进制是48,以48作为ASCII码值

的字符是'0'

    return 0;
}

这些ASCII码值是可以自己写代码验证的,大家也可以自己验证。

关于转义字符我们首先要了解,然后要能在字符串中识别出来。

 

 

9、语句和语句分类

 

C语言的代码是有一条一条的语句构成的,C语言中的语句可分为五类:空语句、表达式语句、函数调用语句、复合语句和控制语句

  (1)空语句

空语句是最简单的,⼀个分号就是⼀条语句,是空语句。

#include <stdio.h>

int main()
{
    ;//空语句

    return 0;
}

空语句,⼀般出现的地⽅是:这⾥需要⼀条语句,但是这个语句不需要做任何事,就可以写⼀个空语句。

 

(2)表达式语句

表达式语句就是在表达式的后边加上分号。如下所⽰:

#include <stdio.h>

int main()
{
    int a = 20;
    int b = 0;
    b = a + 5; //表达式语句

    return 0;
}

 

(3)函数调用语句

函数调用的时候,也会加上分号,就是函数调用语句。

#include <stdio.h>

int Add(int x, int y)
{
    return x+y;
}

int main()
{
    printf("hehe\n");//函数调⽤语句
    int ret = Add(2, 3);//函数调⽤语句
    
    return 0;
}

 

(4)复合语句

复合语句其实就是前⾯讲过的代码块,成对括号中的代码就构成⼀个代码块,也被称为复合语句。1

#include <stdio.h>

void print(int arr[], int sz) //函数的⼤括号中的代码也构成复合语句
{
    int i = 0;
    for(i=0; i<sz; i++)
    {
        printf("%d ", arr[i]);
    }
}

int main()
{
    int i = 0;
    int arr[10] = {0};

    for(i=0; i<10; i++) //for循环的循环体的⼤括号中的就是复合语句
    {
        arr[i] = 10-i;
        printf("%d\n", arr[i]);
    }

    return 0;
}

(5)控制语句

控制语句⽤于控制程序的执⾏流程,以实现程序的各种结构方式(C语⾔⽀持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C语⾔有九种控制语句。

可分成以下三类:

1. 条件判断语句也叫分支语句:if语句、switch语句;

2. 循环执行语句:do while语句、while语句、for语句;

3. 转向语句:break语句、goto语句、continue语句、return语句。

 

 

10、注释是什么?为什么写注释?

注释是对代码的说明,编译器会忽略注释,也就是说,注释对实际代码没有影响。

注释是给程序员自己,或者其他程序员看的。

好的注释可以帮我们更好的理解代码,但是也不要过度注释,不要写没必要的注释。当然不写注释可能会让后期阅读代码的⼈抓狂。

写注释⼀定程度上反应了程序作者的素质,建议大家写必要的注释,在未来找工作的时候,写代码时留下必要的注释也会给面试官留下更好的印象。

 

注释的俩种形式:

(1)/**/ 的形式

/* 注释 */

/*

这是一行注释

*/

这种注释可以插在行内。

int fopen(char* s /* file name */, int mode);

上面示例中, /* file name */ ⽤来对函数参数进行说明,跟在它后面的代码依然会有效执行。

这种注释⼀定不能忘记写结束符号 */ ,否则很容易导致错误。

printf("a "); /* 注释⼀

printf("b ");

printf("c "); /* 注释⼆ */

printf("d ");

上面示例的原意是,第一行和第三行代码的尾部,有两个注释。

但是,第一行注释忘记写结束符号,导致注释一延续到第三行结束。

/**/ 的这个注释也不⽀持嵌套注释, /* 开始注释后,遇到第⼀个 */ 就认为注释结束了。

/*

printf("a ");

printf("b ");

printf("c "); /* 注释⼆ */

printf("d ");

*/

(2)// 的形式 

第⼆种写法是将注释放在双斜杠 // 后⾯,从双斜杠到行尾都属于注释。这种注释只能是单行,可以放在行首,也可以放在一行语句的结尾。这是 C99 标准新增的语法。

// 这是一行注释

int x = 1; // 这也是注释

不管是哪⼀种注释,都不能放在双引号里面。

双引号里面的注释符号,会成为字符串的⼀部分,解释为普通符号,失去注释作用。

printf("// hello /* world */ ");

上面示例中,双引号里面的注释符号,都会被视为普通字符,没有注释作用。

(3)注释会被替换

编译时,注释会被替换成⼀个空格,所以 min/* 这⾥是注释*/Value 会变成 min Value ,而不是 minValue 。

min/* 这⾥是注释*/Value

 

 

 

### GD32F303 I2C Read Operation Tutorial For performing an I2C read operation on the GD32F303 microcontroller, understanding both hardware configuration and software implementation is essential. The following sections provide detailed guidance. #### Hardware Configuration The GD32F303 series supports multiple communication interfaces including I2C. To configure the I2C interface for reading data: - Ensure that SDA (data line) and SCL (clock line) are connected correctly between master and slave devices. - Pull-up resistors should be added to both lines as required by the I2C specification[^1]. #### Software Implementation To implement the I2C read function in code, follow these guidelines: 1. Initialize the I2C peripheral with appropriate parameters such as clock speed and address mode. 2. Generate start condition followed by sending the device's write address. 3. Send register address from where data needs to be read. 4. Generate repeated start then send the device’s read address. 5. Receive byte(s) of data while acknowledging each received byte except the last one. 6. Stop after receiving all expected bytes. Here is a sample C program demonstrating how this can be done using HAL library functions provided specifically for STM32/GD32 platforms: ```c #include "gd32f3x0.h" #include "systick.h" void i2c_init(void); uint8_t i2c_read_byte(uint8_t dev_addr, uint8_t reg); int main(void){ systick_config(); i2c_init(); // Example usage: Reading single byte from specific register at given device address uint8_t value = i2c_read_byte(DEVICE_ADDRESS, REGISTER_TO_READ); } // Function initializes I2C peripherals according to specified parameters values void i2c_init(){ /* Initialization Code Here */ } // Reads a single byte from designated register within target device via I2C bus uint8_t i2c_read_byte(uint8_t dev_addr,uint8_t reg){ uint8_t rx_data; // Start sequence generation here // Transmit Device Address & Write Direction Bit // Send Register Address For Data Retrieval // Repeated Start Sequence Generation // Transmit Device Address With Read Direction Bit Set // Acknowledge Received Byte Except Last One And Store Into Variable 'rx_data' // End Transmission By Generating STOP Condition return rx_data; } ``` This example assumes familiarity with basic embedded programming concepts like setting up system clocks, configuring GPIO pins, etc., which may vary depending upon actual application requirements. --related questions-- 1. What are common issues encountered during I2C communications? 2. How does changing pull-up resistor values affect I2C performance? 3. Can interrupts improve efficiency when handling I2C transactions? 4. Are there any differences between standard-mode and fast-mode operations over I2C?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值