当我用这个命令编译它时...
gcc -Wall -g -c main.c
...它发出这些警告:
source/base64.h: In function ‘base64_decode’:
source/base64.h:45:75: warning: array subscript has type ‘char’ [-Wchar-subscripts]
45 | uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
| ~~~~^~~~~
source/base64.h:46:75: warning: array subscript has type ‘char’ [-Wchar-subscripts]
46 | uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
| ~~~~^~~~~
source/base64.h:47:75: warning: array subscript has type ‘char’ [-Wchar-subscripts]
47 | uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
| ~~~~^~~~~
source/base64.h:48:75: warning: array subscript has type ‘char’ [-Wchar-subscripts]
48 | uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
|
main.c
可以像一样简单
#include "base64.h"
这是 base64.h
的缩减版本,会产生这些警告:
#pragma once
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
static const char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
static char *decoding_table = NULL;
void build_decoding_table() {
decoding_table = malloc(256);
for (int i = 0; i < 64; i++)
decoding_table[(unsigned char) encoding_table[i]] = i;
}
void base64_cleanup() {
free(decoding_table);
}
char *base64_decode(const char *data,
size_t input_length) {
if (decoding_table == NULL) build_decoding_table();
if (input_length % 4 != 0) return NULL;
size_t output_length = input_length / 4 * 3;
if (data[input_length - 1] == '=') (output_length)--;
if (data[input_length - 2] == '=') (output_length)--;
char *decoded_data = malloc(output_length+1);
if (decoded_data == NULL) return NULL;
for (int i = 0, j = 0; i < input_length;) {
uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
uint32_t triple = (sextet_a << 3 * 6)
+ (sextet_b << 2 * 6)
+ (sextet_c << 1 * 6)
+ (sextet_d << 0 * 6);
if (j < output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
if (j < output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
if (j < output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
}
decoded_data[output_length] = '\0';
return decoded_data;
}
如何清除警告?
(int)data[i++]
那样将 data[i++] 转换为 int 时,警告不再显示。
-Wall
选项启用的 GCC 警告中有
-Wchar-subscripts
,这会导致 GCC 对使用
char
类型的值(特别是)作为数组下标发出警告。GCC手册是这样解释的:
如果数组下标的类型为事实上,
char
,则发出警告。这是错误的常见原因,因为程序员经常忘记这种类型在某些机器上已签名。
char
是有符号类型似乎比没有符号类型更常见。您的
base64_decode()
函数与多次使用
data[i++]
作为数组下标的检查发生冲突。如果您可以确定输入(存储在
data
中)仅由有效的base64组成,那么这可能没有意义,因为C要求我知道的每个base-64变体中使用的所有数字都用正值表示。在这种情况下,您可以通过将
-Wno-char-subscripts
添加到 gcc
命令行来抑制这些警告,而无需修改代码。然而,这也会抑制程序其余部分的那些通常合理的警告,因此有点严厉。
如果您愿意修改解码器,那么更温和的做法是添加
data[i++]
的外观到不同整数类型的转换。 unsigned char
将是最好的选择。
另一方面,最好的解决方案可能是选择更好的 Base64 实现。
char
下标只是您正在查看的内容中令人不喜欢的几件事之一。