C安全编程教学-预处理器-不要通过连接创建通用字符名称_java

注:本课程参考文献《C安全编码标准》

 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~

目录

一.不要通过连接创建通用字符名称

1.1背景

1.2注意

1.3案例

1.4安全修改方案

 1.5小练习

1.6答案


一.不要通过连接创建通用字符名称

1.1背景

    C语言标准支持使用通用字符名称来表示那些不在基本字符集中的字符。这些通用字符名称可以用在标识符、字符常量和字符串常量中。具体来说,\Unnnnnnnn形式的通用字符名称表示一个8位数字短标识符为nnnnnnnn的字符,而\unnnn形式的通用字符名称则表示一个4位短标识符为nnnn(相当于8位短标识符为0000nnnn)的字符。

1.2注意

    如果字符序列是通过符号连接来匹配通用字符名称,那么会产生未定义的行为。通常,除非确实有必要,否则在标识符中应当避免使用通用字符名称。

1.3案例

#define assign(uc1,uc2,val) uc1##uc2 = val

void func(void) {
    int \u0401;
    assign(\u04,01,4);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

#define assign(uc1,uc2,val) uc1##uc2 = val

  • 这行代码定义了一个宏assign,它接受三个参数:uc1uc2val
  • uc1##uc2是一个宏的连接操作(token pasting operator),它将uc1uc2两个参数连接成一个新的标识符。
  • = val是将连接后的标识符赋值为val

void func(void) {

  • 定义了一个名为func的函数,该函数没有参数,返回类型为void

int \u0401;

  • 这行代码声明了一个整型变量,但其名称使用了Unicode字符表示法\u0401。在C语言中,\u后面跟随的四个十六进制数字表示一个Unicode字符。\u0401代表的是西里尔字母"Ё"的大写形式。

assign(\u04,01,4);

  • 这行代码使用了之前定义的assign宏来为变量赋值。
  • \u0401作为assign宏的参数,通过宏的连接操作,它们被连接成一个新的标识符,即\u0401,也就是之前声明的变量名。
  • 4作为第三个参数,表示要将变量\u0401的值设置为4

    这部分代码通过符号连接生成通用字符名称。

1.4安全修改方案

#define assign(ucn,val) ucn=val;
void func(void){
    int \u0401;
    assign(\u0401,4);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

 1.5小练习

    请你让这部分代码变得更加安全:

#define CONCAT_AND_ASSIGN(uc1, uc2, val) uc1##uc2 = val  
  
void anotherFunction(void) {  
    int \u0041;  // 'A' in Unicode  
    CONCAT_AND_ASSIGN(\u00, 41, 10);  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

1.6答案

    在这个案例中,CONCAT_AND_ASSIGN 宏同样使用了 token pasting operator (##) 来连接两个参数 uc1 和 uc2,并尝试将结果赋值为 val。然而,这里 \u00 和 41 被用作参数,意图通过连接它们来形成 \u0041,即 ASCII 字符 'A'。

修改方案:

#define ASSIGN(var, val) var = val  
  
void anotherFunction(void) {  
    int \u0041;  // 'A' in Unicode  
    ASSIGN(\u0041, 10);  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

 非常感谢您花时间阅读我的博客,希望这些分享能为您带来启发和帮助。期待您的反馈与交流,让我们共同成长,再次感谢!


 安城安的云世界

 

C安全编程教学-预处理器-不要通过连接创建通用字符名称_c语言_02